Fossil SCM

Minor security enhancements to the optional SEE integration.

mistachkin 2016-10-26 21:31 trunk merge
Commit a8484dc32721016061f055d2edfcb71f140d82c8
+102 -13
--- src/db.c
+++ src/db.c
@@ -870,31 +870,113 @@
870870
db_tolocal_function, 0, 0);
871871
sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0,
872872
db_fromlocal_function, 0, 0);
873873
}
874874
875
+#if USE_SEE
876
+/*
877
+** This is a pointer to the saved database encryption key string.
878
+*/
879
+static char *zSavedKey = 0;
880
+
881
+/*
882
+** This is the size of the saved database encryption key, in bytes.
883
+*/
884
+size_t savedKeySize = 0;
885
+
886
+/*
887
+** This function returns the saved database encryption key -OR- zero if
888
+** no database encryption key is saved.
889
+*/
890
+static char *db_get_saved_encryption_key(){
891
+ return zSavedKey;
892
+}
893
+
894
+/*
895
+** This function arranges for the database encryption key to be securely
896
+** saved in non-pagable memory (on platforms where this is possible).
897
+*/
898
+static void db_save_encryption_key(
899
+ Blob *pKey
900
+){
901
+ void *p = NULL;
902
+ size_t n = 0;
903
+ size_t pageSize = 0;
904
+ size_t blobSize = 0;
905
+
906
+ blobSize = blob_size(pKey);
907
+ if( blobSize==0 ) return;
908
+ fossil_get_page_size(&pageSize);
909
+ assert( pageSize>0 );
910
+ if( blobSize>pageSize ){
911
+ fossil_fatal("key blob too large: %u versus %u", blobSize, pageSize);
912
+ }
913
+ p = fossil_secure_alloc_page(&n);
914
+ assert( p!=NULL );
915
+ assert( n==pageSize );
916
+ assert( n>=blobSize );
917
+ memcpy(p, blob_str(pKey), blobSize);
918
+ zSavedKey = p;
919
+ savedKeySize = n;
920
+}
921
+
922
+/*
923
+** This function arranges for the saved database encryption key to be
924
+** securely zeroed, unlocked (if necessary), and freed.
925
+*/
926
+void db_unsave_encryption_key(){
927
+ fossil_secure_free_page(zSavedKey, savedKeySize);
928
+ zSavedKey = NULL;
929
+ savedKeySize = 0;
930
+}
931
+
932
+/*
933
+** This function sets the saved database encryption key to the specified
934
+** string value, allocating or freeing the underlying memory if needed.
935
+*/
936
+void db_set_saved_encryption_key(
937
+ Blob *pKey
938
+){
939
+ if( zSavedKey!=NULL ){
940
+ size_t blobSize = blob_size(pKey);
941
+ if( blobSize==0 ){
942
+ db_unsave_encryption_key();
943
+ }else{
944
+ if( blobSize>savedKeySize ){
945
+ fossil_fatal("key blob too large: %u versus %u",
946
+ blobSize, savedKeySize);
947
+ }
948
+ fossil_secure_zero(zSavedKey, savedKeySize);
949
+ memcpy(zSavedKey, blob_str(pKey), blobSize);
950
+ }
951
+ }else{
952
+ db_save_encryption_key(pKey);
953
+ }
954
+}
955
+#endif /* USE_SEE */
956
+
875957
/*
876958
** If the database file zDbFile has a name that suggests that it is
877
-** encrypted, then prompt for the encryption key and return it in the
878
-** blob *pKey. Or, if the encryption key has previously been requested,
879
-** just return a copy of the previous result.
959
+** encrypted, then prompt for the database encryption key and return it
960
+** in the blob *pKey. Or, if the encryption key has previously been
961
+** requested, just return a copy of the previous result. The blob in
962
+** *pKey must be initialized.
880963
*/
881
-static void db_encryption_key(
964
+static void db_maybe_obtain_encryption_key(
882965
const char *zDbFile, /* Name of the database file */
883966
Blob *pKey /* Put the encryption key here */
884967
){
885
- blob_init(pKey, 0, 0);
886968
#if USE_SEE
887969
if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
888
- static char *zSavedKey = 0;
889
- if( zSavedKey ){
890
- blob_set(pKey, zSavedKey);
970
+ char *zKey = db_get_saved_encryption_key();
971
+ if( zKey ){
972
+ blob_set(pKey, zKey);
891973
}else{
892974
char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
893975
prompt_for_password(zPrompt, pKey, 0);
894976
fossil_free(zPrompt);
895
- zSavedKey = fossil_strdup(blob_str(pKey));
977
+ db_set_saved_encryption_key(pKey);
896978
}
897979
}
898980
#endif
899981
}
900982
@@ -915,14 +997,16 @@
915997
g.zVfsName
916998
);
917999
if( rc!=SQLITE_OK ){
9181000
db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
9191001
}
920
- db_encryption_key(zDbName, &key);
1002
+ blob_init(&key, 0, 0);
1003
+ db_maybe_obtain_encryption_key(zDbName, &key);
9211004
if( blob_size(&key)>0 ){
9221005
char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
9231006
sqlite3_exec(db, zCmd, 0, 0, 0);
1007
+ fossil_secure_zero(zCmd, strlen(zCmd));
9241008
sqlite3_free(zCmd);
9251009
}
9261010
blob_reset(&key);
9271011
sqlite3_busy_timeout(db, 5000);
9281012
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
@@ -955,14 +1039,19 @@
9551039
/*
9561040
** zDbName is the name of a database file. Attach zDbName using
9571041
** the name zLabel.
9581042
*/
9591043
void db_attach(const char *zDbName, const char *zLabel){
1044
+ char *zCmd;
9601045
Blob key;
961
- db_encryption_key(zDbName, &key);
962
- db_multi_exec("ATTACH DATABASE %Q AS %Q KEY %Q",
963
- zDbName, zLabel, blob_str(&key));
1046
+ blob_init(&key, 0, 0);
1047
+ db_maybe_obtain_encryption_key(zDbName, &key);
1048
+ zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY %Q",
1049
+ zDbName, zLabel, blob_str(&key));
1050
+ db_multi_exec(zCmd /*works-like:""*/);
1051
+ fossil_secure_zero(zCmd, strlen(zCmd));
1052
+ sqlite3_free(zCmd);
9641053
blob_reset(&key);
9651054
}
9661055
9671056
/*
9681057
** Change the schema name of the "main" database to zLabel.
9691058
--- src/db.c
+++ src/db.c
@@ -870,31 +870,113 @@
870 db_tolocal_function, 0, 0);
871 sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0,
872 db_fromlocal_function, 0, 0);
873 }
874
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
875 /*
876 ** If the database file zDbFile has a name that suggests that it is
877 ** encrypted, then prompt for the encryption key and return it in the
878 ** blob *pKey. Or, if the encryption key has previously been requested,
879 ** just return a copy of the previous result.
 
880 */
881 static void db_encryption_key(
882 const char *zDbFile, /* Name of the database file */
883 Blob *pKey /* Put the encryption key here */
884 ){
885 blob_init(pKey, 0, 0);
886 #if USE_SEE
887 if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
888 static char *zSavedKey = 0;
889 if( zSavedKey ){
890 blob_set(pKey, zSavedKey);
891 }else{
892 char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
893 prompt_for_password(zPrompt, pKey, 0);
894 fossil_free(zPrompt);
895 zSavedKey = fossil_strdup(blob_str(pKey));
896 }
897 }
898 #endif
899 }
900
@@ -915,14 +997,16 @@
915 g.zVfsName
916 );
917 if( rc!=SQLITE_OK ){
918 db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
919 }
920 db_encryption_key(zDbName, &key);
 
921 if( blob_size(&key)>0 ){
922 char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
923 sqlite3_exec(db, zCmd, 0, 0, 0);
 
924 sqlite3_free(zCmd);
925 }
926 blob_reset(&key);
927 sqlite3_busy_timeout(db, 5000);
928 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
@@ -955,14 +1039,19 @@
955 /*
956 ** zDbName is the name of a database file. Attach zDbName using
957 ** the name zLabel.
958 */
959 void db_attach(const char *zDbName, const char *zLabel){
 
960 Blob key;
961 db_encryption_key(zDbName, &key);
962 db_multi_exec("ATTACH DATABASE %Q AS %Q KEY %Q",
963 zDbName, zLabel, blob_str(&key));
 
 
 
 
964 blob_reset(&key);
965 }
966
967 /*
968 ** Change the schema name of the "main" database to zLabel.
969
--- src/db.c
+++ src/db.c
@@ -870,31 +870,113 @@
870 db_tolocal_function, 0, 0);
871 sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0,
872 db_fromlocal_function, 0, 0);
873 }
874
875 #if USE_SEE
876 /*
877 ** This is a pointer to the saved database encryption key string.
878 */
879 static char *zSavedKey = 0;
880
881 /*
882 ** This is the size of the saved database encryption key, in bytes.
883 */
884 size_t savedKeySize = 0;
885
886 /*
887 ** This function returns the saved database encryption key -OR- zero if
888 ** no database encryption key is saved.
889 */
890 static char *db_get_saved_encryption_key(){
891 return zSavedKey;
892 }
893
894 /*
895 ** This function arranges for the database encryption key to be securely
896 ** saved in non-pagable memory (on platforms where this is possible).
897 */
898 static void db_save_encryption_key(
899 Blob *pKey
900 ){
901 void *p = NULL;
902 size_t n = 0;
903 size_t pageSize = 0;
904 size_t blobSize = 0;
905
906 blobSize = blob_size(pKey);
907 if( blobSize==0 ) return;
908 fossil_get_page_size(&pageSize);
909 assert( pageSize>0 );
910 if( blobSize>pageSize ){
911 fossil_fatal("key blob too large: %u versus %u", blobSize, pageSize);
912 }
913 p = fossil_secure_alloc_page(&n);
914 assert( p!=NULL );
915 assert( n==pageSize );
916 assert( n>=blobSize );
917 memcpy(p, blob_str(pKey), blobSize);
918 zSavedKey = p;
919 savedKeySize = n;
920 }
921
922 /*
923 ** This function arranges for the saved database encryption key to be
924 ** securely zeroed, unlocked (if necessary), and freed.
925 */
926 void db_unsave_encryption_key(){
927 fossil_secure_free_page(zSavedKey, savedKeySize);
928 zSavedKey = NULL;
929 savedKeySize = 0;
930 }
931
932 /*
933 ** This function sets the saved database encryption key to the specified
934 ** string value, allocating or freeing the underlying memory if needed.
935 */
936 void db_set_saved_encryption_key(
937 Blob *pKey
938 ){
939 if( zSavedKey!=NULL ){
940 size_t blobSize = blob_size(pKey);
941 if( blobSize==0 ){
942 db_unsave_encryption_key();
943 }else{
944 if( blobSize>savedKeySize ){
945 fossil_fatal("key blob too large: %u versus %u",
946 blobSize, savedKeySize);
947 }
948 fossil_secure_zero(zSavedKey, savedKeySize);
949 memcpy(zSavedKey, blob_str(pKey), blobSize);
950 }
951 }else{
952 db_save_encryption_key(pKey);
953 }
954 }
955 #endif /* USE_SEE */
956
957 /*
958 ** If the database file zDbFile has a name that suggests that it is
959 ** encrypted, then prompt for the database encryption key and return it
960 ** in the blob *pKey. Or, if the encryption key has previously been
961 ** requested, just return a copy of the previous result. The blob in
962 ** *pKey must be initialized.
963 */
964 static void db_maybe_obtain_encryption_key(
965 const char *zDbFile, /* Name of the database file */
966 Blob *pKey /* Put the encryption key here */
967 ){
 
968 #if USE_SEE
969 if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
970 char *zKey = db_get_saved_encryption_key();
971 if( zKey ){
972 blob_set(pKey, zKey);
973 }else{
974 char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
975 prompt_for_password(zPrompt, pKey, 0);
976 fossil_free(zPrompt);
977 db_set_saved_encryption_key(pKey);
978 }
979 }
980 #endif
981 }
982
@@ -915,14 +997,16 @@
997 g.zVfsName
998 );
999 if( rc!=SQLITE_OK ){
1000 db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
1001 }
1002 blob_init(&key, 0, 0);
1003 db_maybe_obtain_encryption_key(zDbName, &key);
1004 if( blob_size(&key)>0 ){
1005 char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
1006 sqlite3_exec(db, zCmd, 0, 0, 0);
1007 fossil_secure_zero(zCmd, strlen(zCmd));
1008 sqlite3_free(zCmd);
1009 }
1010 blob_reset(&key);
1011 sqlite3_busy_timeout(db, 5000);
1012 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
@@ -955,14 +1039,19 @@
1039 /*
1040 ** zDbName is the name of a database file. Attach zDbName using
1041 ** the name zLabel.
1042 */
1043 void db_attach(const char *zDbName, const char *zLabel){
1044 char *zCmd;
1045 Blob key;
1046 blob_init(&key, 0, 0);
1047 db_maybe_obtain_encryption_key(zDbName, &key);
1048 zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY %Q",
1049 zDbName, zLabel, blob_str(&key));
1050 db_multi_exec(zCmd /*works-like:""*/);
1051 fossil_secure_zero(zCmd, strlen(zCmd));
1052 sqlite3_free(zCmd);
1053 blob_reset(&key);
1054 }
1055
1056 /*
1057 ** Change the schema name of the "main" database to zLabel.
1058
+102 -13
--- src/db.c
+++ src/db.c
@@ -870,31 +870,113 @@
870870
db_tolocal_function, 0, 0);
871871
sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0,
872872
db_fromlocal_function, 0, 0);
873873
}
874874
875
+#if USE_SEE
876
+/*
877
+** This is a pointer to the saved database encryption key string.
878
+*/
879
+static char *zSavedKey = 0;
880
+
881
+/*
882
+** This is the size of the saved database encryption key, in bytes.
883
+*/
884
+size_t savedKeySize = 0;
885
+
886
+/*
887
+** This function returns the saved database encryption key -OR- zero if
888
+** no database encryption key is saved.
889
+*/
890
+static char *db_get_saved_encryption_key(){
891
+ return zSavedKey;
892
+}
893
+
894
+/*
895
+** This function arranges for the database encryption key to be securely
896
+** saved in non-pagable memory (on platforms where this is possible).
897
+*/
898
+static void db_save_encryption_key(
899
+ Blob *pKey
900
+){
901
+ void *p = NULL;
902
+ size_t n = 0;
903
+ size_t pageSize = 0;
904
+ size_t blobSize = 0;
905
+
906
+ blobSize = blob_size(pKey);
907
+ if( blobSize==0 ) return;
908
+ fossil_get_page_size(&pageSize);
909
+ assert( pageSize>0 );
910
+ if( blobSize>pageSize ){
911
+ fossil_fatal("key blob too large: %u versus %u", blobSize, pageSize);
912
+ }
913
+ p = fossil_secure_alloc_page(&n);
914
+ assert( p!=NULL );
915
+ assert( n==pageSize );
916
+ assert( n>=blobSize );
917
+ memcpy(p, blob_str(pKey), blobSize);
918
+ zSavedKey = p;
919
+ savedKeySize = n;
920
+}
921
+
922
+/*
923
+** This function arranges for the saved database encryption key to be
924
+** securely zeroed, unlocked (if necessary), and freed.
925
+*/
926
+void db_unsave_encryption_key(){
927
+ fossil_secure_free_page(zSavedKey, savedKeySize);
928
+ zSavedKey = NULL;
929
+ savedKeySize = 0;
930
+}
931
+
932
+/*
933
+** This function sets the saved database encryption key to the specified
934
+** string value, allocating or freeing the underlying memory if needed.
935
+*/
936
+void db_set_saved_encryption_key(
937
+ Blob *pKey
938
+){
939
+ if( zSavedKey!=NULL ){
940
+ size_t blobSize = blob_size(pKey);
941
+ if( blobSize==0 ){
942
+ db_unsave_encryption_key();
943
+ }else{
944
+ if( blobSize>savedKeySize ){
945
+ fossil_fatal("key blob too large: %u versus %u",
946
+ blobSize, savedKeySize);
947
+ }
948
+ fossil_secure_zero(zSavedKey, savedKeySize);
949
+ memcpy(zSavedKey, blob_str(pKey), blobSize);
950
+ }
951
+ }else{
952
+ db_save_encryption_key(pKey);
953
+ }
954
+}
955
+#endif /* USE_SEE */
956
+
875957
/*
876958
** If the database file zDbFile has a name that suggests that it is
877
-** encrypted, then prompt for the encryption key and return it in the
878
-** blob *pKey. Or, if the encryption key has previously been requested,
879
-** just return a copy of the previous result.
959
+** encrypted, then prompt for the database encryption key and return it
960
+** in the blob *pKey. Or, if the encryption key has previously been
961
+** requested, just return a copy of the previous result. The blob in
962
+** *pKey must be initialized.
880963
*/
881
-static void db_encryption_key(
964
+static void db_maybe_obtain_encryption_key(
882965
const char *zDbFile, /* Name of the database file */
883966
Blob *pKey /* Put the encryption key here */
884967
){
885
- blob_init(pKey, 0, 0);
886968
#if USE_SEE
887969
if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
888
- static char *zSavedKey = 0;
889
- if( zSavedKey ){
890
- blob_set(pKey, zSavedKey);
970
+ char *zKey = db_get_saved_encryption_key();
971
+ if( zKey ){
972
+ blob_set(pKey, zKey);
891973
}else{
892974
char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
893975
prompt_for_password(zPrompt, pKey, 0);
894976
fossil_free(zPrompt);
895
- zSavedKey = fossil_strdup(blob_str(pKey));
977
+ db_set_saved_encryption_key(pKey);
896978
}
897979
}
898980
#endif
899981
}
900982
@@ -915,14 +997,16 @@
915997
g.zVfsName
916998
);
917999
if( rc!=SQLITE_OK ){
9181000
db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
9191001
}
920
- db_encryption_key(zDbName, &key);
1002
+ blob_init(&key, 0, 0);
1003
+ db_maybe_obtain_encryption_key(zDbName, &key);
9211004
if( blob_size(&key)>0 ){
9221005
char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
9231006
sqlite3_exec(db, zCmd, 0, 0, 0);
1007
+ fossil_secure_zero(zCmd, strlen(zCmd));
9241008
sqlite3_free(zCmd);
9251009
}
9261010
blob_reset(&key);
9271011
sqlite3_busy_timeout(db, 5000);
9281012
sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
@@ -955,14 +1039,19 @@
9551039
/*
9561040
** zDbName is the name of a database file. Attach zDbName using
9571041
** the name zLabel.
9581042
*/
9591043
void db_attach(const char *zDbName, const char *zLabel){
1044
+ char *zCmd;
9601045
Blob key;
961
- db_encryption_key(zDbName, &key);
962
- db_multi_exec("ATTACH DATABASE %Q AS %Q KEY %Q",
963
- zDbName, zLabel, blob_str(&key));
1046
+ blob_init(&key, 0, 0);
1047
+ db_maybe_obtain_encryption_key(zDbName, &key);
1048
+ zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY %Q",
1049
+ zDbName, zLabel, blob_str(&key));
1050
+ db_multi_exec(zCmd /*works-like:""*/);
1051
+ fossil_secure_zero(zCmd, strlen(zCmd));
1052
+ sqlite3_free(zCmd);
9641053
blob_reset(&key);
9651054
}
9661055
9671056
/*
9681057
** Change the schema name of the "main" database to zLabel.
9691058
--- src/db.c
+++ src/db.c
@@ -870,31 +870,113 @@
870 db_tolocal_function, 0, 0);
871 sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0,
872 db_fromlocal_function, 0, 0);
873 }
874
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
875 /*
876 ** If the database file zDbFile has a name that suggests that it is
877 ** encrypted, then prompt for the encryption key and return it in the
878 ** blob *pKey. Or, if the encryption key has previously been requested,
879 ** just return a copy of the previous result.
 
880 */
881 static void db_encryption_key(
882 const char *zDbFile, /* Name of the database file */
883 Blob *pKey /* Put the encryption key here */
884 ){
885 blob_init(pKey, 0, 0);
886 #if USE_SEE
887 if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
888 static char *zSavedKey = 0;
889 if( zSavedKey ){
890 blob_set(pKey, zSavedKey);
891 }else{
892 char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
893 prompt_for_password(zPrompt, pKey, 0);
894 fossil_free(zPrompt);
895 zSavedKey = fossil_strdup(blob_str(pKey));
896 }
897 }
898 #endif
899 }
900
@@ -915,14 +997,16 @@
915 g.zVfsName
916 );
917 if( rc!=SQLITE_OK ){
918 db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
919 }
920 db_encryption_key(zDbName, &key);
 
921 if( blob_size(&key)>0 ){
922 char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
923 sqlite3_exec(db, zCmd, 0, 0, 0);
 
924 sqlite3_free(zCmd);
925 }
926 blob_reset(&key);
927 sqlite3_busy_timeout(db, 5000);
928 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
@@ -955,14 +1039,19 @@
955 /*
956 ** zDbName is the name of a database file. Attach zDbName using
957 ** the name zLabel.
958 */
959 void db_attach(const char *zDbName, const char *zLabel){
 
960 Blob key;
961 db_encryption_key(zDbName, &key);
962 db_multi_exec("ATTACH DATABASE %Q AS %Q KEY %Q",
963 zDbName, zLabel, blob_str(&key));
 
 
 
 
964 blob_reset(&key);
965 }
966
967 /*
968 ** Change the schema name of the "main" database to zLabel.
969
--- src/db.c
+++ src/db.c
@@ -870,31 +870,113 @@
870 db_tolocal_function, 0, 0);
871 sqlite3_create_function(db, "fromLocal", 0, SQLITE_UTF8, 0,
872 db_fromlocal_function, 0, 0);
873 }
874
875 #if USE_SEE
876 /*
877 ** This is a pointer to the saved database encryption key string.
878 */
879 static char *zSavedKey = 0;
880
881 /*
882 ** This is the size of the saved database encryption key, in bytes.
883 */
884 size_t savedKeySize = 0;
885
886 /*
887 ** This function returns the saved database encryption key -OR- zero if
888 ** no database encryption key is saved.
889 */
890 static char *db_get_saved_encryption_key(){
891 return zSavedKey;
892 }
893
894 /*
895 ** This function arranges for the database encryption key to be securely
896 ** saved in non-pagable memory (on platforms where this is possible).
897 */
898 static void db_save_encryption_key(
899 Blob *pKey
900 ){
901 void *p = NULL;
902 size_t n = 0;
903 size_t pageSize = 0;
904 size_t blobSize = 0;
905
906 blobSize = blob_size(pKey);
907 if( blobSize==0 ) return;
908 fossil_get_page_size(&pageSize);
909 assert( pageSize>0 );
910 if( blobSize>pageSize ){
911 fossil_fatal("key blob too large: %u versus %u", blobSize, pageSize);
912 }
913 p = fossil_secure_alloc_page(&n);
914 assert( p!=NULL );
915 assert( n==pageSize );
916 assert( n>=blobSize );
917 memcpy(p, blob_str(pKey), blobSize);
918 zSavedKey = p;
919 savedKeySize = n;
920 }
921
922 /*
923 ** This function arranges for the saved database encryption key to be
924 ** securely zeroed, unlocked (if necessary), and freed.
925 */
926 void db_unsave_encryption_key(){
927 fossil_secure_free_page(zSavedKey, savedKeySize);
928 zSavedKey = NULL;
929 savedKeySize = 0;
930 }
931
932 /*
933 ** This function sets the saved database encryption key to the specified
934 ** string value, allocating or freeing the underlying memory if needed.
935 */
936 void db_set_saved_encryption_key(
937 Blob *pKey
938 ){
939 if( zSavedKey!=NULL ){
940 size_t blobSize = blob_size(pKey);
941 if( blobSize==0 ){
942 db_unsave_encryption_key();
943 }else{
944 if( blobSize>savedKeySize ){
945 fossil_fatal("key blob too large: %u versus %u",
946 blobSize, savedKeySize);
947 }
948 fossil_secure_zero(zSavedKey, savedKeySize);
949 memcpy(zSavedKey, blob_str(pKey), blobSize);
950 }
951 }else{
952 db_save_encryption_key(pKey);
953 }
954 }
955 #endif /* USE_SEE */
956
957 /*
958 ** If the database file zDbFile has a name that suggests that it is
959 ** encrypted, then prompt for the database encryption key and return it
960 ** in the blob *pKey. Or, if the encryption key has previously been
961 ** requested, just return a copy of the previous result. The blob in
962 ** *pKey must be initialized.
963 */
964 static void db_maybe_obtain_encryption_key(
965 const char *zDbFile, /* Name of the database file */
966 Blob *pKey /* Put the encryption key here */
967 ){
 
968 #if USE_SEE
969 if( sqlite3_strglob("*.efossil", zDbFile)==0 ){
970 char *zKey = db_get_saved_encryption_key();
971 if( zKey ){
972 blob_set(pKey, zKey);
973 }else{
974 char *zPrompt = mprintf("\rencryption key for '%s': ", zDbFile);
975 prompt_for_password(zPrompt, pKey, 0);
976 fossil_free(zPrompt);
977 db_set_saved_encryption_key(pKey);
978 }
979 }
980 #endif
981 }
982
@@ -915,14 +997,16 @@
997 g.zVfsName
998 );
999 if( rc!=SQLITE_OK ){
1000 db_err("[%s]: %s", zDbName, sqlite3_errmsg(db));
1001 }
1002 blob_init(&key, 0, 0);
1003 db_maybe_obtain_encryption_key(zDbName, &key);
1004 if( blob_size(&key)>0 ){
1005 char *zCmd = sqlite3_mprintf("PRAGMA key(%Q)", blob_str(&key));
1006 sqlite3_exec(db, zCmd, 0, 0, 0);
1007 fossil_secure_zero(zCmd, strlen(zCmd));
1008 sqlite3_free(zCmd);
1009 }
1010 blob_reset(&key);
1011 sqlite3_busy_timeout(db, 5000);
1012 sqlite3_wal_autocheckpoint(db, 1); /* Set to checkpoint frequently */
@@ -955,14 +1039,19 @@
1039 /*
1040 ** zDbName is the name of a database file. Attach zDbName using
1041 ** the name zLabel.
1042 */
1043 void db_attach(const char *zDbName, const char *zLabel){
1044 char *zCmd;
1045 Blob key;
1046 blob_init(&key, 0, 0);
1047 db_maybe_obtain_encryption_key(zDbName, &key);
1048 zCmd = sqlite3_mprintf("ATTACH DATABASE %Q AS %Q KEY %Q",
1049 zDbName, zLabel, blob_str(&key));
1050 db_multi_exec(zCmd /*works-like:""*/);
1051 fossil_secure_zero(zCmd, strlen(zCmd));
1052 sqlite3_free(zCmd);
1053 blob_reset(&key);
1054 }
1055
1056 /*
1057 ** Change the schema name of the "main" database to zLabel.
1058
+12
--- src/main.c
+++ src/main.c
@@ -299,10 +299,22 @@
299299
/*
300300
** atexit() handler which frees up "some" of the resources
301301
** used by fossil.
302302
*/
303303
static void fossil_atexit(void) {
304
+#if USE_SEE
305
+ /*
306
+ ** Zero, unlock, and free the saved database encryption key now.
307
+ */
308
+ db_unsave_encryption_key();
309
+#endif
310
+#if defined(_WIN32) || defined(__BIONIC__)
311
+ /*
312
+ ** Free the secure getpass() buffer now.
313
+ */
314
+ freepass();
315
+#endif
304316
#if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \
305317
defined(USE_TCL_STUBS)
306318
/*
307319
** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash
308320
** when exiting while a stubs-enabled Tcl is still loaded. This is due to
309321
--- src/main.c
+++ src/main.c
@@ -299,10 +299,22 @@
299 /*
300 ** atexit() handler which frees up "some" of the resources
301 ** used by fossil.
302 */
303 static void fossil_atexit(void) {
 
 
 
 
 
 
 
 
 
 
 
 
304 #if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \
305 defined(USE_TCL_STUBS)
306 /*
307 ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash
308 ** when exiting while a stubs-enabled Tcl is still loaded. This is due to
309
--- src/main.c
+++ src/main.c
@@ -299,10 +299,22 @@
299 /*
300 ** atexit() handler which frees up "some" of the resources
301 ** used by fossil.
302 */
303 static void fossil_atexit(void) {
304 #if USE_SEE
305 /*
306 ** Zero, unlock, and free the saved database encryption key now.
307 */
308 db_unsave_encryption_key();
309 #endif
310 #if defined(_WIN32) || defined(__BIONIC__)
311 /*
312 ** Free the secure getpass() buffer now.
313 */
314 freepass();
315 #endif
316 #if defined(_WIN32) && !defined(_WIN64) && defined(FOSSIL_ENABLE_TCL) && \
317 defined(USE_TCL_STUBS)
318 /*
319 ** If Tcl is compiled on Windows using the latest MinGW, Fossil can crash
320 ** when exiting while a stubs-enabled Tcl is still loaded. This is due to
321
+33 -16
--- src/user.c
+++ src/user.c
@@ -19,14 +19,10 @@
1919
** querying information about users.
2020
*/
2121
#include "config.h"
2222
#include "user.h"
2323
24
-#if defined(_WIN32)
25
-#include <conio.h>
26
-#endif
27
-
2824
/*
2925
** Strip leading and trailing space from a string and add the string
3026
** onto the end of a blob.
3127
*/
3228
static void strip_string(Blob *pBlob, char *z){
@@ -43,53 +39,74 @@
4339
}
4440
blob_append(pBlob, z, -1);
4541
}
4642
4743
#if defined(_WIN32) || defined(__BIONIC__)
48
-#ifdef __MINGW32__
44
+#ifdef _WIN32
4945
#include <conio.h>
5046
#endif
47
+
5148
/*
52
-** getpass for Windows and Android
49
+** getpass() for Windows and Android.
5350
*/
51
+static char *zPwdBuffer = 0;
52
+static size_t nPwdBuffer = 0;
53
+
5454
static char *getpass(const char *prompt){
55
- static char pwd[64];
55
+ char *zPwd;
56
+ size_t nPwd;
5657
size_t i;
5758
59
+ if( zPwdBuffer==0 ){
60
+ zPwdBuffer = fossil_secure_alloc_page(&nPwdBuffer);
61
+ assert( zPwdBuffer );
62
+ }else{
63
+ fossil_secure_zero(zPwdBuffer, nPwdBuffer);
64
+ }
65
+ zPwd = zPwdBuffer;
66
+ nPwd = nPwdBuffer;
5867
fputs(prompt,stderr);
5968
fflush(stderr);
60
- for(i=0; i<sizeof(pwd)-1; ++i){
69
+ assert( zPwd!=0 );
70
+ assert( nPwd>0 );
71
+ for(i=0; i<nPwd-1; ++i){
6172
#if defined(_WIN32)
62
- pwd[i] = _getch();
73
+ zPwd[i] = _getch();
6374
#else
64
- pwd[i] = getc(stdin);
75
+ zPwd[i] = getc(stdin);
6576
#endif
66
- if(pwd[i]=='\r' || pwd[i]=='\n'){
77
+ if(zPwd[i]=='\r' || zPwd[i]=='\n'){
6778
break;
6879
}
6980
/* BS or DEL */
70
- else if(i>0 && (pwd[i]==8 || pwd[i]==127)){
81
+ else if(i>0 && (zPwd[i]==8 || zPwd[i]==127)){
7182
i -= 2;
7283
continue;
7384
}
7485
/* CTRL-C */
75
- else if(pwd[i]==3) {
86
+ else if(zPwd[i]==3) {
7687
i=0;
7788
break;
7889
}
7990
/* ESC */
80
- else if(pwd[i]==27){
91
+ else if(zPwd[i]==27){
8192
i=0;
8293
break;
8394
}
8495
else{
8596
fputc('*',stderr);
8697
}
8798
}
88
- pwd[i]='\0';
99
+ zPwd[i]='\0';
89100
fputs("\n", stderr);
90
- return pwd;
101
+ assert( zPwd==zPwdBuffer );
102
+ return zPwd;
103
+}
104
+void freepass(){
105
+ if( !zPwdBuffer ) return;
106
+ assert( nPwdBuffer>0 );
107
+ fossil_secure_free_page(zPwdBuffer, nPwdBuffer);
91108
}
92109
#endif
93110
94111
#if defined(_WIN32) || defined(WIN32)
95112
# include <io.h>
96113
--- src/user.c
+++ src/user.c
@@ -19,14 +19,10 @@
19 ** querying information about users.
20 */
21 #include "config.h"
22 #include "user.h"
23
24 #if defined(_WIN32)
25 #include <conio.h>
26 #endif
27
28 /*
29 ** Strip leading and trailing space from a string and add the string
30 ** onto the end of a blob.
31 */
32 static void strip_string(Blob *pBlob, char *z){
@@ -43,53 +39,74 @@
43 }
44 blob_append(pBlob, z, -1);
45 }
46
47 #if defined(_WIN32) || defined(__BIONIC__)
48 #ifdef __MINGW32__
49 #include <conio.h>
50 #endif
 
51 /*
52 ** getpass for Windows and Android
53 */
 
 
 
54 static char *getpass(const char *prompt){
55 static char pwd[64];
 
56 size_t i;
57
 
 
 
 
 
 
 
 
58 fputs(prompt,stderr);
59 fflush(stderr);
60 for(i=0; i<sizeof(pwd)-1; ++i){
 
 
61 #if defined(_WIN32)
62 pwd[i] = _getch();
63 #else
64 pwd[i] = getc(stdin);
65 #endif
66 if(pwd[i]=='\r' || pwd[i]=='\n'){
67 break;
68 }
69 /* BS or DEL */
70 else if(i>0 && (pwd[i]==8 || pwd[i]==127)){
71 i -= 2;
72 continue;
73 }
74 /* CTRL-C */
75 else if(pwd[i]==3) {
76 i=0;
77 break;
78 }
79 /* ESC */
80 else if(pwd[i]==27){
81 i=0;
82 break;
83 }
84 else{
85 fputc('*',stderr);
86 }
87 }
88 pwd[i]='\0';
89 fputs("\n", stderr);
90 return pwd;
 
 
 
 
 
 
91 }
92 #endif
93
94 #if defined(_WIN32) || defined(WIN32)
95 # include <io.h>
96
--- src/user.c
+++ src/user.c
@@ -19,14 +19,10 @@
19 ** querying information about users.
20 */
21 #include "config.h"
22 #include "user.h"
23
 
 
 
 
24 /*
25 ** Strip leading and trailing space from a string and add the string
26 ** onto the end of a blob.
27 */
28 static void strip_string(Blob *pBlob, char *z){
@@ -43,53 +39,74 @@
39 }
40 blob_append(pBlob, z, -1);
41 }
42
43 #if defined(_WIN32) || defined(__BIONIC__)
44 #ifdef _WIN32
45 #include <conio.h>
46 #endif
47
48 /*
49 ** getpass() for Windows and Android.
50 */
51 static char *zPwdBuffer = 0;
52 static size_t nPwdBuffer = 0;
53
54 static char *getpass(const char *prompt){
55 char *zPwd;
56 size_t nPwd;
57 size_t i;
58
59 if( zPwdBuffer==0 ){
60 zPwdBuffer = fossil_secure_alloc_page(&nPwdBuffer);
61 assert( zPwdBuffer );
62 }else{
63 fossil_secure_zero(zPwdBuffer, nPwdBuffer);
64 }
65 zPwd = zPwdBuffer;
66 nPwd = nPwdBuffer;
67 fputs(prompt,stderr);
68 fflush(stderr);
69 assert( zPwd!=0 );
70 assert( nPwd>0 );
71 for(i=0; i<nPwd-1; ++i){
72 #if defined(_WIN32)
73 zPwd[i] = _getch();
74 #else
75 zPwd[i] = getc(stdin);
76 #endif
77 if(zPwd[i]=='\r' || zPwd[i]=='\n'){
78 break;
79 }
80 /* BS or DEL */
81 else if(i>0 && (zPwd[i]==8 || zPwd[i]==127)){
82 i -= 2;
83 continue;
84 }
85 /* CTRL-C */
86 else if(zPwd[i]==3) {
87 i=0;
88 break;
89 }
90 /* ESC */
91 else if(zPwd[i]==27){
92 i=0;
93 break;
94 }
95 else{
96 fputc('*',stderr);
97 }
98 }
99 zPwd[i]='\0';
100 fputs("\n", stderr);
101 assert( zPwd==zPwdBuffer );
102 return zPwd;
103 }
104 void freepass(){
105 if( !zPwdBuffer ) return;
106 assert( nPwdBuffer>0 );
107 fossil_secure_free_page(zPwdBuffer, nPwdBuffer);
108 }
109 #endif
110
111 #if defined(_WIN32) || defined(WIN32)
112 # include <io.h>
113
+33 -16
--- src/user.c
+++ src/user.c
@@ -19,14 +19,10 @@
1919
** querying information about users.
2020
*/
2121
#include "config.h"
2222
#include "user.h"
2323
24
-#if defined(_WIN32)
25
-#include <conio.h>
26
-#endif
27
-
2824
/*
2925
** Strip leading and trailing space from a string and add the string
3026
** onto the end of a blob.
3127
*/
3228
static void strip_string(Blob *pBlob, char *z){
@@ -43,53 +39,74 @@
4339
}
4440
blob_append(pBlob, z, -1);
4541
}
4642
4743
#if defined(_WIN32) || defined(__BIONIC__)
48
-#ifdef __MINGW32__
44
+#ifdef _WIN32
4945
#include <conio.h>
5046
#endif
47
+
5148
/*
52
-** getpass for Windows and Android
49
+** getpass() for Windows and Android.
5350
*/
51
+static char *zPwdBuffer = 0;
52
+static size_t nPwdBuffer = 0;
53
+
5454
static char *getpass(const char *prompt){
55
- static char pwd[64];
55
+ char *zPwd;
56
+ size_t nPwd;
5657
size_t i;
5758
59
+ if( zPwdBuffer==0 ){
60
+ zPwdBuffer = fossil_secure_alloc_page(&nPwdBuffer);
61
+ assert( zPwdBuffer );
62
+ }else{
63
+ fossil_secure_zero(zPwdBuffer, nPwdBuffer);
64
+ }
65
+ zPwd = zPwdBuffer;
66
+ nPwd = nPwdBuffer;
5867
fputs(prompt,stderr);
5968
fflush(stderr);
60
- for(i=0; i<sizeof(pwd)-1; ++i){
69
+ assert( zPwd!=0 );
70
+ assert( nPwd>0 );
71
+ for(i=0; i<nPwd-1; ++i){
6172
#if defined(_WIN32)
62
- pwd[i] = _getch();
73
+ zPwd[i] = _getch();
6374
#else
64
- pwd[i] = getc(stdin);
75
+ zPwd[i] = getc(stdin);
6576
#endif
66
- if(pwd[i]=='\r' || pwd[i]=='\n'){
77
+ if(zPwd[i]=='\r' || zPwd[i]=='\n'){
6778
break;
6879
}
6980
/* BS or DEL */
70
- else if(i>0 && (pwd[i]==8 || pwd[i]==127)){
81
+ else if(i>0 && (zPwd[i]==8 || zPwd[i]==127)){
7182
i -= 2;
7283
continue;
7384
}
7485
/* CTRL-C */
75
- else if(pwd[i]==3) {
86
+ else if(zPwd[i]==3) {
7687
i=0;
7788
break;
7889
}
7990
/* ESC */
80
- else if(pwd[i]==27){
91
+ else if(zPwd[i]==27){
8192
i=0;
8293
break;
8394
}
8495
else{
8596
fputc('*',stderr);
8697
}
8798
}
88
- pwd[i]='\0';
99
+ zPwd[i]='\0';
89100
fputs("\n", stderr);
90
- return pwd;
101
+ assert( zPwd==zPwdBuffer );
102
+ return zPwd;
103
+}
104
+void freepass(){
105
+ if( !zPwdBuffer ) return;
106
+ assert( nPwdBuffer>0 );
107
+ fossil_secure_free_page(zPwdBuffer, nPwdBuffer);
91108
}
92109
#endif
93110
94111
#if defined(_WIN32) || defined(WIN32)
95112
# include <io.h>
96113
--- src/user.c
+++ src/user.c
@@ -19,14 +19,10 @@
19 ** querying information about users.
20 */
21 #include "config.h"
22 #include "user.h"
23
24 #if defined(_WIN32)
25 #include <conio.h>
26 #endif
27
28 /*
29 ** Strip leading and trailing space from a string and add the string
30 ** onto the end of a blob.
31 */
32 static void strip_string(Blob *pBlob, char *z){
@@ -43,53 +39,74 @@
43 }
44 blob_append(pBlob, z, -1);
45 }
46
47 #if defined(_WIN32) || defined(__BIONIC__)
48 #ifdef __MINGW32__
49 #include <conio.h>
50 #endif
 
51 /*
52 ** getpass for Windows and Android
53 */
 
 
 
54 static char *getpass(const char *prompt){
55 static char pwd[64];
 
56 size_t i;
57
 
 
 
 
 
 
 
 
58 fputs(prompt,stderr);
59 fflush(stderr);
60 for(i=0; i<sizeof(pwd)-1; ++i){
 
 
61 #if defined(_WIN32)
62 pwd[i] = _getch();
63 #else
64 pwd[i] = getc(stdin);
65 #endif
66 if(pwd[i]=='\r' || pwd[i]=='\n'){
67 break;
68 }
69 /* BS or DEL */
70 else if(i>0 && (pwd[i]==8 || pwd[i]==127)){
71 i -= 2;
72 continue;
73 }
74 /* CTRL-C */
75 else if(pwd[i]==3) {
76 i=0;
77 break;
78 }
79 /* ESC */
80 else if(pwd[i]==27){
81 i=0;
82 break;
83 }
84 else{
85 fputc('*',stderr);
86 }
87 }
88 pwd[i]='\0';
89 fputs("\n", stderr);
90 return pwd;
 
 
 
 
 
 
91 }
92 #endif
93
94 #if defined(_WIN32) || defined(WIN32)
95 # include <io.h>
96
--- src/user.c
+++ src/user.c
@@ -19,14 +19,10 @@
19 ** querying information about users.
20 */
21 #include "config.h"
22 #include "user.h"
23
 
 
 
 
24 /*
25 ** Strip leading and trailing space from a string and add the string
26 ** onto the end of a blob.
27 */
28 static void strip_string(Blob *pBlob, char *z){
@@ -43,53 +39,74 @@
39 }
40 blob_append(pBlob, z, -1);
41 }
42
43 #if defined(_WIN32) || defined(__BIONIC__)
44 #ifdef _WIN32
45 #include <conio.h>
46 #endif
47
48 /*
49 ** getpass() for Windows and Android.
50 */
51 static char *zPwdBuffer = 0;
52 static size_t nPwdBuffer = 0;
53
54 static char *getpass(const char *prompt){
55 char *zPwd;
56 size_t nPwd;
57 size_t i;
58
59 if( zPwdBuffer==0 ){
60 zPwdBuffer = fossil_secure_alloc_page(&nPwdBuffer);
61 assert( zPwdBuffer );
62 }else{
63 fossil_secure_zero(zPwdBuffer, nPwdBuffer);
64 }
65 zPwd = zPwdBuffer;
66 nPwd = nPwdBuffer;
67 fputs(prompt,stderr);
68 fflush(stderr);
69 assert( zPwd!=0 );
70 assert( nPwd>0 );
71 for(i=0; i<nPwd-1; ++i){
72 #if defined(_WIN32)
73 zPwd[i] = _getch();
74 #else
75 zPwd[i] = getc(stdin);
76 #endif
77 if(zPwd[i]=='\r' || zPwd[i]=='\n'){
78 break;
79 }
80 /* BS or DEL */
81 else if(i>0 && (zPwd[i]==8 || zPwd[i]==127)){
82 i -= 2;
83 continue;
84 }
85 /* CTRL-C */
86 else if(zPwd[i]==3) {
87 i=0;
88 break;
89 }
90 /* ESC */
91 else if(zPwd[i]==27){
92 i=0;
93 break;
94 }
95 else{
96 fputc('*',stderr);
97 }
98 }
99 zPwd[i]='\0';
100 fputs("\n", stderr);
101 assert( zPwd==zPwdBuffer );
102 return zPwd;
103 }
104 void freepass(){
105 if( !zPwdBuffer ) return;
106 assert( nPwdBuffer>0 );
107 fossil_secure_free_page(zPwdBuffer, nPwdBuffer);
108 }
109 #endif
110
111 #if defined(_WIN32) || defined(WIN32)
112 # include <io.h>
113
+57
--- src/util.c
+++ src/util.c
@@ -55,10 +55,67 @@
5555
}
5656
void *fossil_realloc(void *p, size_t n){
5757
p = realloc(p, n);
5858
if( p==0 ) fossil_panic("out of memory");
5959
return p;
60
+}
61
+void fossil_secure_zero(void *p, size_t n){
62
+ volatile unsigned char *vp = (volatile unsigned char *)p;
63
+ size_t i;
64
+
65
+ if( p==0 ) return;
66
+ assert( n>0 );
67
+ if( n==0 ) return;
68
+ for(i=0; i<n; i++){ vp[i] ^= 0xFF; }
69
+ for(i=0; i<n; i++){ vp[i] ^= vp[i]; }
70
+}
71
+void fossil_get_page_size(size_t *piPageSize){
72
+#if defined(_WIN32)
73
+ SYSTEM_INFO sysInfo;
74
+ memset(&sysInfo, 0, sizeof(SYSTEM_INFO));
75
+ GetSystemInfo(&sysInfo);
76
+ *piPageSize = (size_t)sysInfo.dwPageSize;
77
+#else
78
+ *piPageSize = 4096; /* FIXME: What for POSIX? */
79
+#endif
80
+}
81
+void *fossil_secure_alloc_page(size_t *pN){
82
+ void *p;
83
+ size_t pageSize;
84
+
85
+ fossil_get_page_size(&pageSize);
86
+ assert( pageSize>0 );
87
+ assert( pageSize%2==0 );
88
+#if defined(_WIN32)
89
+ p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
90
+ if( p==NULL ){
91
+ fossil_fatal("VirtualAlloc failed: %lu\n", GetLastError());
92
+ }
93
+ if( !VirtualLock(p, pageSize) ){
94
+ fossil_fatal("VirtualLock failed: %lu\n", GetLastError());
95
+ }
96
+#else
97
+ p = fossil_malloc(pageSize);
98
+#endif
99
+ fossil_secure_zero(p, pageSize);
100
+ if( pN ) *pN = pageSize;
101
+ return p;
102
+}
103
+void fossil_secure_free_page(void *p, size_t n){
104
+ if( !p ) return;
105
+ assert( n>0 );
106
+ fossil_secure_zero(p, n);
107
+#if defined(_WIN32)
108
+ if( !VirtualUnlock(p, n) ){
109
+ fossil_fatal("VirtualUnlock failed: %lu\n", GetLastError());
110
+ }
111
+ if( !VirtualFree(p, 0, MEM_RELEASE) ){
112
+ fossil_fatal("VirtualFree failed: %lu\n", GetLastError());
113
+ }
114
+#else
115
+ fossil_free(p);
116
+#endif
60117
}
61118
62119
/*
63120
** This function implements a cross-platform "system()" interface.
64121
*/
65122
--- src/util.c
+++ src/util.c
@@ -55,10 +55,67 @@
55 }
56 void *fossil_realloc(void *p, size_t n){
57 p = realloc(p, n);
58 if( p==0 ) fossil_panic("out of memory");
59 return p;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60 }
61
62 /*
63 ** This function implements a cross-platform "system()" interface.
64 */
65
--- src/util.c
+++ src/util.c
@@ -55,10 +55,67 @@
55 }
56 void *fossil_realloc(void *p, size_t n){
57 p = realloc(p, n);
58 if( p==0 ) fossil_panic("out of memory");
59 return p;
60 }
61 void fossil_secure_zero(void *p, size_t n){
62 volatile unsigned char *vp = (volatile unsigned char *)p;
63 size_t i;
64
65 if( p==0 ) return;
66 assert( n>0 );
67 if( n==0 ) return;
68 for(i=0; i<n; i++){ vp[i] ^= 0xFF; }
69 for(i=0; i<n; i++){ vp[i] ^= vp[i]; }
70 }
71 void fossil_get_page_size(size_t *piPageSize){
72 #if defined(_WIN32)
73 SYSTEM_INFO sysInfo;
74 memset(&sysInfo, 0, sizeof(SYSTEM_INFO));
75 GetSystemInfo(&sysInfo);
76 *piPageSize = (size_t)sysInfo.dwPageSize;
77 #else
78 *piPageSize = 4096; /* FIXME: What for POSIX? */
79 #endif
80 }
81 void *fossil_secure_alloc_page(size_t *pN){
82 void *p;
83 size_t pageSize;
84
85 fossil_get_page_size(&pageSize);
86 assert( pageSize>0 );
87 assert( pageSize%2==0 );
88 #if defined(_WIN32)
89 p = VirtualAlloc(NULL, pageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
90 if( p==NULL ){
91 fossil_fatal("VirtualAlloc failed: %lu\n", GetLastError());
92 }
93 if( !VirtualLock(p, pageSize) ){
94 fossil_fatal("VirtualLock failed: %lu\n", GetLastError());
95 }
96 #else
97 p = fossil_malloc(pageSize);
98 #endif
99 fossil_secure_zero(p, pageSize);
100 if( pN ) *pN = pageSize;
101 return p;
102 }
103 void fossil_secure_free_page(void *p, size_t n){
104 if( !p ) return;
105 assert( n>0 );
106 fossil_secure_zero(p, n);
107 #if defined(_WIN32)
108 if( !VirtualUnlock(p, n) ){
109 fossil_fatal("VirtualUnlock failed: %lu\n", GetLastError());
110 }
111 if( !VirtualFree(p, 0, MEM_RELEASE) ){
112 fossil_fatal("VirtualFree failed: %lu\n", GetLastError());
113 }
114 #else
115 fossil_free(p);
116 #endif
117 }
118
119 /*
120 ** This function implements a cross-platform "system()" interface.
121 */
122
--- www/changes.wiki
+++ www/changes.wiki
@@ -8,10 +8,12 @@
88
from the "ticketchng" table.
99
* Enhance the "brlist" page to make use of branch colors.
1010
* Remove the "fusefs" command from builds that do not have the underlying
1111
support enabled.
1212
* Fixes for incremental git import/export.
13
+ * Minor security enhancements to
14
+ [./encryptedrepos.wiki|encrypted repositories].
1315
* TH1 enhancements:
1416
<ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li>
1517
<li>Add <nowiki>[unversioned list]</nowiki> command.</li>
1618
<li>Add project_description variable.</li>
1719
</ul>
1820
--- www/changes.wiki
+++ www/changes.wiki
@@ -8,10 +8,12 @@
8 from the "ticketchng" table.
9 * Enhance the "brlist" page to make use of branch colors.
10 * Remove the "fusefs" command from builds that do not have the underlying
11 support enabled.
12 * Fixes for incremental git import/export.
 
 
13 * TH1 enhancements:
14 <ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li>
15 <li>Add <nowiki>[unversioned list]</nowiki> command.</li>
16 <li>Add project_description variable.</li>
17 </ul>
18
--- www/changes.wiki
+++ www/changes.wiki
@@ -8,10 +8,12 @@
8 from the "ticketchng" table.
9 * Enhance the "brlist" page to make use of branch colors.
10 * Remove the "fusefs" command from builds that do not have the underlying
11 support enabled.
12 * Fixes for incremental git import/export.
13 * Minor security enhancements to
14 [./encryptedrepos.wiki|encrypted repositories].
15 * TH1 enhancements:
16 <ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li>
17 <li>Add <nowiki>[unversioned list]</nowiki> command.</li>
18 <li>Add project_description variable.</li>
19 </ul>
20
--- www/changes.wiki
+++ www/changes.wiki
@@ -8,10 +8,12 @@
88
from the "ticketchng" table.
99
* Enhance the "brlist" page to make use of branch colors.
1010
* Remove the "fusefs" command from builds that do not have the underlying
1111
support enabled.
1212
* Fixes for incremental git import/export.
13
+ * Minor security enhancements to
14
+ [./encryptedrepos.wiki|encrypted repositories].
1315
* TH1 enhancements:
1416
<ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li>
1517
<li>Add <nowiki>[unversioned list]</nowiki> command.</li>
1618
<li>Add project_description variable.</li>
1719
</ul>
1820
--- www/changes.wiki
+++ www/changes.wiki
@@ -8,10 +8,12 @@
8 from the "ticketchng" table.
9 * Enhance the "brlist" page to make use of branch colors.
10 * Remove the "fusefs" command from builds that do not have the underlying
11 support enabled.
12 * Fixes for incremental git import/export.
 
 
13 * TH1 enhancements:
14 <ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li>
15 <li>Add <nowiki>[unversioned list]</nowiki> command.</li>
16 <li>Add project_description variable.</li>
17 </ul>
18
--- www/changes.wiki
+++ www/changes.wiki
@@ -8,10 +8,12 @@
8 from the "ticketchng" table.
9 * Enhance the "brlist" page to make use of branch colors.
10 * Remove the "fusefs" command from builds that do not have the underlying
11 support enabled.
12 * Fixes for incremental git import/export.
13 * Minor security enhancements to
14 [./encryptedrepos.wiki|encrypted repositories].
15 * TH1 enhancements:
16 <ul><li>Add <nowiki>[unversioned content]</nowiki> command.</li>
17 <li>Add <nowiki>[unversioned list]</nowiki> command.</li>
18 <li>Add project_description variable.</li>
19 </ul>
20

Keyboard Shortcuts

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