Fossil SCM

If the FOSSIL_SECURITY_LEVEL environment variable is 2 or more, then present a simple substitution matrix when entering passwords, as a defense against key loggers. For FOSSIL_SECURITY_LEVEL of 1 or more, do not remember the remote-url password.

drh 2016-06-24 03:36 trunk
Commit e1034c4c35195ef61602d4ec05a72e8681de6a98
1 file changed +77
+77
--- src/user.c
+++ src/user.c
@@ -97,10 +97,79 @@
9797
# undef popen
9898
# define popen _popen
9999
# undef pclose
100100
# define pclose _pclose
101101
#endif
102
+
103
+/*
104
+** Scramble substitution matrix:
105
+*/
106
+static char aSubst[256];
107
+
108
+/*
109
+** Descramble the password
110
+*/
111
+static void userDescramble(char *z){
112
+ int i;
113
+ for(i=0; z[i]; i++) z[i] = aSubst[(unsigned char)z[i]];
114
+}
115
+
116
+/* Print a string in 5-letter groups */
117
+static void printFive(const unsigned char *z){
118
+ int i;
119
+ for(i=0; z[i]; i++){
120
+ if( i>0 && (i%5)==0 ) putchar(' ');
121
+ putchar(z[i]);
122
+ }
123
+ putchar('\n');
124
+}
125
+
126
+/* Return a pseudo-random integer between 0 and N-1 */
127
+static int randint(int N){
128
+ unsigned char x;
129
+ assert( N<256 );
130
+ sqlite3_randomness(1, &x);
131
+ return x % N;
132
+}
133
+
134
+/*
135
+** Generate and print a random scrambling of letters a through z (omitting x)
136
+** and set up the aSubst[] matrix to descramble.
137
+*/
138
+static void userGenerateScrambleCode(void){
139
+ unsigned char zOrig[30];
140
+ unsigned char zA[30];
141
+ unsigned char zB[30];
142
+ int nA = 25;
143
+ int nB = 0;
144
+ int i;
145
+ memcpy(zOrig, "abcdefghijklmnopqrstuvwyz", nA+1);
146
+ memcpy(zA, zOrig, nA+1);
147
+ assert( nA==(int)strlen((char*)zA) );
148
+ for(i=0; i<sizeof(aSubst); i++) aSubst[i] = i;
149
+ printFive(zA);
150
+ while( nA>0 ){
151
+ int x = randint(nA);
152
+ zB[nB++] = zA[x];
153
+ zA[x] = zA[--nA];
154
+ }
155
+ assert( nB==25 );
156
+ zB[nB] = 0;
157
+ printFive(zB);
158
+ for(i=0; i<nB; i++) aSubst[zB[i]] = zOrig[i];
159
+}
160
+
161
+/*
162
+** Return the value of the FOSSIL_SECURITY_LEVEL environment variable.
163
+** Or return 0 if that variable does not exist.
164
+*/
165
+int fossil_security_level(void){
166
+ const char *zLevel = fossil_getenv("FOSSIL_SECURITY_LEVEL");
167
+ if( zLevel==0 ) return 0;
168
+ return atoi(zLevel);
169
+}
170
+
102171
103172
/*
104173
** Do a single prompt for a passphrase. Store the results in the blob.
105174
**
106175
** If the FOSSIL_PWREADER environment variable is set, then it will
@@ -117,10 +186,11 @@
117186
** on subsequent calls to this same routine.
118187
*/
119188
static void prompt_for_passphrase(const char *zPrompt, Blob *pPassphrase){
120189
char *z;
121190
const char *zProg = fossil_getenv("FOSSIL_PWREADER");
191
+ const char *zSecure;
122192
if( zProg && zProg[0] ){
123193
static char zPass[100];
124194
Blob cmd;
125195
FILE *in;
126196
blob_zero(&cmd);
@@ -129,10 +199,16 @@
129199
in = popen(blob_str(&cmd), "r");
130200
fgets(zPass, sizeof(zPass), in);
131201
pclose(in);
132202
blob_reset(&cmd);
133203
z = zPass;
204
+ }else if( fossil_security_level()>=2 ){
205
+ userGenerateScrambleCode();
206
+ z = getpass(zPrompt);
207
+ if( z ) userDescramble(z);
208
+ printf("\033[3A\033[J"); /* Erase previous three lines */
209
+ fflush(stdout);
134210
}else{
135211
z = getpass(zPrompt);
136212
}
137213
strip_string(pPassphrase, z);
138214
}
@@ -180,10 +256,11 @@
180256
char c;
181257
const char *old = db_get("last-sync-pw", 0);
182258
if( (old!=0) && fossil_strcmp(unobscure(old), passwd)==0 ){
183259
return 0;
184260
}
261
+ if( fossil_security_level()>=1 ) return 0;
185262
prompt_user("remember password (Y/n)? ", &x);
186263
c = blob_str(&x)[0];
187264
blob_reset(&x);
188265
return ( c!='n' && c!='N' );
189266
}
190267
--- src/user.c
+++ src/user.c
@@ -97,10 +97,79 @@
97 # undef popen
98 # define popen _popen
99 # undef pclose
100 # define pclose _pclose
101 #endif
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
103 /*
104 ** Do a single prompt for a passphrase. Store the results in the blob.
105 **
106 ** If the FOSSIL_PWREADER environment variable is set, then it will
@@ -117,10 +186,11 @@
117 ** on subsequent calls to this same routine.
118 */
119 static void prompt_for_passphrase(const char *zPrompt, Blob *pPassphrase){
120 char *z;
121 const char *zProg = fossil_getenv("FOSSIL_PWREADER");
 
122 if( zProg && zProg[0] ){
123 static char zPass[100];
124 Blob cmd;
125 FILE *in;
126 blob_zero(&cmd);
@@ -129,10 +199,16 @@
129 in = popen(blob_str(&cmd), "r");
130 fgets(zPass, sizeof(zPass), in);
131 pclose(in);
132 blob_reset(&cmd);
133 z = zPass;
 
 
 
 
 
 
134 }else{
135 z = getpass(zPrompt);
136 }
137 strip_string(pPassphrase, z);
138 }
@@ -180,10 +256,11 @@
180 char c;
181 const char *old = db_get("last-sync-pw", 0);
182 if( (old!=0) && fossil_strcmp(unobscure(old), passwd)==0 ){
183 return 0;
184 }
 
185 prompt_user("remember password (Y/n)? ", &x);
186 c = blob_str(&x)[0];
187 blob_reset(&x);
188 return ( c!='n' && c!='N' );
189 }
190
--- src/user.c
+++ src/user.c
@@ -97,10 +97,79 @@
97 # undef popen
98 # define popen _popen
99 # undef pclose
100 # define pclose _pclose
101 #endif
102
103 /*
104 ** Scramble substitution matrix:
105 */
106 static char aSubst[256];
107
108 /*
109 ** Descramble the password
110 */
111 static void userDescramble(char *z){
112 int i;
113 for(i=0; z[i]; i++) z[i] = aSubst[(unsigned char)z[i]];
114 }
115
116 /* Print a string in 5-letter groups */
117 static void printFive(const unsigned char *z){
118 int i;
119 for(i=0; z[i]; i++){
120 if( i>0 && (i%5)==0 ) putchar(' ');
121 putchar(z[i]);
122 }
123 putchar('\n');
124 }
125
126 /* Return a pseudo-random integer between 0 and N-1 */
127 static int randint(int N){
128 unsigned char x;
129 assert( N<256 );
130 sqlite3_randomness(1, &x);
131 return x % N;
132 }
133
134 /*
135 ** Generate and print a random scrambling of letters a through z (omitting x)
136 ** and set up the aSubst[] matrix to descramble.
137 */
138 static void userGenerateScrambleCode(void){
139 unsigned char zOrig[30];
140 unsigned char zA[30];
141 unsigned char zB[30];
142 int nA = 25;
143 int nB = 0;
144 int i;
145 memcpy(zOrig, "abcdefghijklmnopqrstuvwyz", nA+1);
146 memcpy(zA, zOrig, nA+1);
147 assert( nA==(int)strlen((char*)zA) );
148 for(i=0; i<sizeof(aSubst); i++) aSubst[i] = i;
149 printFive(zA);
150 while( nA>0 ){
151 int x = randint(nA);
152 zB[nB++] = zA[x];
153 zA[x] = zA[--nA];
154 }
155 assert( nB==25 );
156 zB[nB] = 0;
157 printFive(zB);
158 for(i=0; i<nB; i++) aSubst[zB[i]] = zOrig[i];
159 }
160
161 /*
162 ** Return the value of the FOSSIL_SECURITY_LEVEL environment variable.
163 ** Or return 0 if that variable does not exist.
164 */
165 int fossil_security_level(void){
166 const char *zLevel = fossil_getenv("FOSSIL_SECURITY_LEVEL");
167 if( zLevel==0 ) return 0;
168 return atoi(zLevel);
169 }
170
171
172 /*
173 ** Do a single prompt for a passphrase. Store the results in the blob.
174 **
175 ** If the FOSSIL_PWREADER environment variable is set, then it will
@@ -117,10 +186,11 @@
186 ** on subsequent calls to this same routine.
187 */
188 static void prompt_for_passphrase(const char *zPrompt, Blob *pPassphrase){
189 char *z;
190 const char *zProg = fossil_getenv("FOSSIL_PWREADER");
191 const char *zSecure;
192 if( zProg && zProg[0] ){
193 static char zPass[100];
194 Blob cmd;
195 FILE *in;
196 blob_zero(&cmd);
@@ -129,10 +199,16 @@
199 in = popen(blob_str(&cmd), "r");
200 fgets(zPass, sizeof(zPass), in);
201 pclose(in);
202 blob_reset(&cmd);
203 z = zPass;
204 }else if( fossil_security_level()>=2 ){
205 userGenerateScrambleCode();
206 z = getpass(zPrompt);
207 if( z ) userDescramble(z);
208 printf("\033[3A\033[J"); /* Erase previous three lines */
209 fflush(stdout);
210 }else{
211 z = getpass(zPrompt);
212 }
213 strip_string(pPassphrase, z);
214 }
@@ -180,10 +256,11 @@
256 char c;
257 const char *old = db_get("last-sync-pw", 0);
258 if( (old!=0) && fossil_strcmp(unobscure(old), passwd)==0 ){
259 return 0;
260 }
261 if( fossil_security_level()>=1 ) return 0;
262 prompt_user("remember password (Y/n)? ", &x);
263 c = blob_str(&x)[0];
264 blob_reset(&x);
265 return ( c!='n' && c!='N' );
266 }
267

Keyboard Shortcuts

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