Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Infrastructure in place on the client side to encrypt sync traffic. This is mostly untested so far because we do not yet have a server that understands encrypted traffic. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | experimental |
| Files: | files | file ages | folders |
| SHA1: |
9a23c348b1bb1daa7a7a8517f1bc2786 |
| User & Date: | drh 2009-03-27 14:32:33.000 |
Context
|
2009-03-29
| ||
| 11:41 | If no userid is specified in the URL then the client omits the login card from its request. ... (Closed-Leaf check-in: 09d6a6eb16 user: drh tags: experimental) | |
|
2009-03-27
| ||
| 14:32 | Infrastructure in place on the client side to encrypt sync traffic. This is mostly untested so far because we do not yet have a server that understands encrypted traffic. ... (check-in: 9a23c348b1 user: drh tags: experimental) | |
|
2009-03-26
| ||
| 23:26 | Completed implementation of utility functions to encrypt and decrypt blobs. ... (check-in: bf16ab9b7b user: drh tags: experimental) | |
Changes
Changes to src/blob.c.
| ︙ | ︙ | |||
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 |
** prior to the current cursor position is ignored.
**
** Because of the prepended nonce, the output will be 20 bytes larger
** than the input.
**
** pOut should be initialized prior to invoking this routine. pOut might
** already contain other content. The encryption is appended to pOut.
*/
void blob_encrypt(Blob *pIn, const char *zPassword, Blob *pOut){
char *aNonce;
char *aIn;
int nIn;
char *aOut;
aIn = pIn->aData;
aIn += pIn->iCursor;
nIn = pIn->nUsed - pIn->iCursor;
if( nIn<=0 ) return;
blob_resize(pOut, pOut->nUsed+nIn+N_NONCE);
aOut = pOut->aData;
aOut += pOut->iCursor;
| > > > | 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 |
** prior to the current cursor position is ignored.
**
** Because of the prepended nonce, the output will be 20 bytes larger
** than the input.
**
** pOut should be initialized prior to invoking this routine. pOut might
** already contain other content. The encryption is appended to pOut.
** The encryption cannot be done in place; pOut cannot be the same blob
** as pIn.
*/
void blob_encrypt(Blob *pIn, const char *zPassword, Blob *pOut){
char *aNonce;
char *aIn;
int nIn;
char *aOut;
assert( pIn!=pOut );
aIn = pIn->aData;
aIn += pIn->iCursor;
nIn = pIn->nUsed - pIn->iCursor;
if( nIn<=0 ) return;
blob_resize(pOut, pOut->nUsed+nIn+N_NONCE);
aOut = pOut->aData;
aOut += pOut->iCursor;
|
| ︙ | ︙ | |||
959 960 961 962 963 964 965 | ** used, the original unencrypted text will be written into pOut. ** ** Only that portion of pIn beginning at the current cursor location and ** extending to the end of the blob is decrypted. Any content of pIn ** prior to the current cursor position is ignored. ** ** pOut should be initialized prior to invoking this routine. pOut might | | > > > | > > > > > > | 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 1000 |
** used, the original unencrypted text will be written into pOut.
**
** Only that portion of pIn beginning at the current cursor location and
** extending to the end of the blob is decrypted. Any content of pIn
** prior to the current cursor position is ignored.
**
** pOut should be initialized prior to invoking this routine. pOut might
** already contain other content. The decryption is appended to pOut
** starting at its current cursor position. Decryption can be done
** in place; it is acceptable for pOut and pIn to be the same blob.
*/
void blob_decrypt(Blob *pIn, const char *zPassword, Blob *pOut){
char *aNonce;
char *aIn;
int nIn;
char *aOut;
aIn = pIn->aData;
aNonce = aIn + pIn->iCursor;
aIn = aNonce + N_NONCE;
nIn = pIn->nUsed - pIn->iCursor - N_NONCE;
if( pOut!=pIn ){
blob_resize(pOut, pOut->iCursor + nIn);
}
aOut = pOut->aData;
aOut += pOut->iCursor;
rc4_coder(zPassword, aNonce, N_NONCE, aIn, nIn, aOut);
if( pOut==pIn ){
pOut->nUsed = pOut->iCursor + nIn;
aOut[nIn] = 0;
pOut->iCursor = pOut->nUsed;
}
}
/*
** COMMAND: test-encrypt PASSWORD PLAINTEXT CYPHERTEXT
*/
void encrypt_test_cmd(void){
|
| ︙ | ︙ |
Changes to src/http.c.
| ︙ | ︙ | |||
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
return 0;
}
blob_append(pBlob, rbuf, read);
}
return blob_size(pBlob);
}
#endif
/*
** Make a single attempt to talk to the server. Return TRUE on success
** and FALSE on a failure.
**
** pHeader contains the HTTP header. pPayload contains the content.
** The content of the reply is written into pReply. pReply is assumed
** to be uninitialized prior to this call.
**
** If an error occurs, this routine return false, resets pReply and
** closes the persistent connection, if any.
*/
static int http_send_recv(Blob *pHeader, Blob *pPayload, Blob *pReply){
int closeConnection=1; /* default to closing the connection */
int rc;
int iLength;
int iHttpVersion;
int i;
int nRead;
char zLine[2000];
if( pSocket==0 && http_open_socket() ){
return 0;
}
iLength = -1;
#ifdef __MINGW32__
| > > > > > > > > > > > > > > > > > > > > > > > | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
return 0;
}
blob_append(pBlob, rbuf, read);
}
return blob_size(pBlob);
}
#endif
/*
** zLine is a line from the header of an HTTP reply. Find the
** "argument" to this header line. The argument is the first non-whitespace
** character following the first ":" in the line. The argument consists of
** non-whitespace and non-semicolon characters. Zero-terminate the argument
** before returning.
*/
static char *header_arg(char *zIn){
char *z;
while( *zIn && *zIn!=':' ){ zIn++; }
if( *zIn==':' ){ zIn++; }
while( isspace(*zIn) ){ zIn++; }
for(z=zIn; *z && *z!=';' && !isspace(*z); z++){}
*z = 0;
return zIn;
}
/*
** Make a single attempt to talk to the server. Return TRUE on success
** and FALSE on a failure.
**
** pHeader contains the HTTP header. pPayload contains the content.
** The content of the reply is written into pReply. pReply is assumed
** to be uninitialized prior to this call.
**
** pPayload has already been compressed and/or encrypted prior to being
** passed into this function. pReply will be decrypted and/or decompressed
** as required by this function, based on the Content-Type of the reply.
**
** If an error occurs, this routine return false, resets pReply and
** closes the persistent connection, if any.
*/
static int http_send_recv(Blob *pHeader, Blob *pPayload, Blob *pReply){
int closeConnection=1; /* default to closing the connection */
int rc;
int iLength;
int iHttpVersion;
int i;
int nRead;
int needDecrypt = 0;
int needDecompress = 0;
char zLine[2000];
if( pSocket==0 && http_open_socket() ){
return 0;
}
iLength = -1;
#ifdef __MINGW32__
|
| ︙ | ︙ | |||
217 218 219 220 221 222 223 |
if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
if( rc!=200 ) goto write_err;
if( iHttpVersion==0 ){
closeConnection = 1;
}else{
closeConnection = 0;
}
| | | | | | | | > > > > > > > > | > | 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
if( sscanf(zLine, "HTTP/1.%d %d", &iHttpVersion, &rc)!=2 ) goto write_err;
if( rc!=200 ) goto write_err;
if( iHttpVersion==0 ){
closeConnection = 1;
}else{
closeConnection = 0;
}
}else if( strncasecmp(zLine,"content-length:",15)==0 ){
iLength = atoi(header_arg(zLine));
}else if( strncasecmp(zLine, "connection:", 11)==0 ){
int c = header_arg(zLine)[0];
if( c=='c' || c=='C' ){
closeConnection = 1; /* Connection: close */
}else if( c=='k' || c=='K' ){
closeConnection = 0; /* Connection: keep-alive */
}
}else if( strncasecmp(zLine, "content-type:", 13)==0 ){
const char *zType = header_arg(zLine);
if( strcmp(zType, "application/x-fossil")==0 ){
needDecompress = 1;
needDecrypt = 0;
}else if( strcmp(zType, "application/x-fossil-secure")==0 ){
needDecompress = 1;
needDecrypt = 1;
}
}
}
if( iLength<0 ) goto write_err;
nRead = socket_read_blob(pReply, pSocket, iLength);
#else
rc = fwrite(blob_buffer(pHeader), 1, blob_size(pHeader), pSocket);
if( rc!=blob_size(pHeader) ) goto write_err;
rc = fwrite(blob_buffer(pPayload), 1, blob_size(pPayload), pSocket);
|
| ︙ | ︙ | |||
249 250 251 252 253 254 255 |
closeConnection = 0; /* Connection: keep-alive */
}
while( fgets(zLine, sizeof(zLine), pSocket) ){
for(i=0; zLine[i] && zLine[i]!='\n' && zLine[i]!='\r'; i++){}
if( i==0 ) break;
zLine[i] = 0;
if( strncasecmp(zLine,"content-length:",15)==0 ){
| | | | | > > > > > > > > | > > > > > > > | 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 |
closeConnection = 0; /* Connection: keep-alive */
}
while( fgets(zLine, sizeof(zLine), pSocket) ){
for(i=0; zLine[i] && zLine[i]!='\n' && zLine[i]!='\r'; i++){}
if( i==0 ) break;
zLine[i] = 0;
if( strncasecmp(zLine,"content-length:",15)==0 ){
iLength = atoi(header_arg(zLine));
}else if( strncasecmp(zLine, "connection:", 11)==0 ){
int c = header_arg(zLine)[0];
if( c=='c' || c=='C' ){
closeConnection = 1; /* Connection: close */
}else if( c=='k' || c=='K' ){
closeConnection = 0; /* Connection: keep-alive */
}
}else if( strncasecmp(zLine, "content-type:", 13)==0 ){
const char *zType = header_arg(zLine);
if( strcmp(zType, "application/x-fossil")==0 ){
needDecompress = 1;
needDecrypt = 0;
}else if( strcmp(zType, "application/x-fossil-secure")==0 ){
needDecompress = 1;
needDecrypt = 1;
}
}
}
if( iLength<0 ) goto write_err;
nRead = blob_read_from_channel(pReply, pSocket, iLength);
#endif
if( nRead!=iLength ){
blob_reset(pReply);
goto write_err;
}
if( closeConnection ){
http_close();
}
if( needDecrypt ){
blob_decrypt(pReply, g.urlPasswd, pReply);
}
if( needDecompress ){
blob_uncompress(pReply, pReply);
}
return 1;
write_err:
http_close();
return 0;
}
|
| ︙ | ︙ | |||
339 340 341 342 343 344 345 | } blob_reset(&nonce); blob_reset(&pw); blob_reset(&sig); /* Construct the payload, which includes the login card. */ | > > > > | > > | | 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 |
}
blob_reset(&nonce);
blob_reset(&pw);
blob_reset(&sig);
/* Construct the payload, which includes the login card.
*/
if( g.fHttpSecure && g.urlPasswd[0] ){
blob_compress(pSend, pSend);
payload = login;
blob_encrypt(pSend, g.urlPasswd, &payload);
}else if( g.fHttpTrace ){
payload = login;
blob_append(&payload, blob_buffer(pSend), blob_size(pSend));
}else{
blob_compress2(&login, pSend, &payload);
blob_reset(&login);
}
/* Construct the HTTP request header
*/
blob_zero(&hdr);
i = strlen(g.urlPath);
if( i>0 && g.urlPath[i-1]=='/' ){
zSep = "";
}else{
zSep = "/";
}
blob_appendf(&hdr, "POST %s%sxfer HTTP/1.1\r\n", g.urlPath, zSep);
blob_appendf(&hdr, "Host: %s\r\n", g.urlHostname);
blob_appendf(&hdr, "User-Agent: Fossil/" MANIFEST_VERSION "\r\n");
if( g.fHttpSecure && g.urlPasswd[0] ){
blob_appendf(&hdr, "Content-Type: application/x-fossil-secure\r\n");
}else if( g.fHttpTrace ){
blob_appendf(&hdr, "Content-Type: application/x-fossil-debug\r\n");
}else{
blob_appendf(&hdr, "Content-Type: application/x-fossil\r\n");
}
blob_appendf(&hdr, "Content-Length: %d\r\n\r\n", blob_size(&payload));
if( g.fHttpTrace ){
|
| ︙ | ︙ | |||
401 402 403 404 405 406 407 |
if( cnt>=2 ){
fossil_fatal("connection to server failed");
}
blob_reset(&hdr);
blob_reset(&payload);
/* Process the reply. pRecv contains only the payload of the
| | > < < | 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 |
if( cnt>=2 ){
fossil_fatal("connection to server failed");
}
blob_reset(&hdr);
blob_reset(&payload);
/* Process the reply. pRecv contains only the payload of the
** reply message, not the header. pRecv has already been decrypted
** and decompressed
*/
if( g.fHttpTrace ){
printf("HTTP RECEIVE:\n%s\n=======================\n", blob_str(pRecv));
}
}
/*
** Make sure the socket to the HTTP server is closed
*/
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
60 61 62 63 64 65 66 67 68 69 70 71 72 73 | char *zRepositoryName; /* Name of the repository database */ int localOpen; /* True if the local database is open */ char *zLocalRoot; /* The directory holding the local database */ int minPrefix; /* Number of digits needed for a distinct UUID */ int fSqlTrace; /* True if -sqltrace flag is present */ int fSqlPrint; /* True if -sqlprint flag is present */ int fHttpTrace; /* Trace outbound HTTP requests */ int fNoSync; /* Do not do an autosync even. --nosync */ char *zPath; /* Name of webpage being served */ char *zExtra; /* Extra path information past the webpage name */ char *zBaseURL; /* Full text of the URL being served */ char *zTop; /* Parent directory of zPath */ const char *zContentType; /* The content type of the input HTTP request */ int iErrPriority; /* Priority of current error message */ | > | 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | char *zRepositoryName; /* Name of the repository database */ int localOpen; /* True if the local database is open */ char *zLocalRoot; /* The directory holding the local database */ int minPrefix; /* Number of digits needed for a distinct UUID */ int fSqlTrace; /* True if -sqltrace flag is present */ int fSqlPrint; /* True if -sqlprint flag is present */ int fHttpTrace; /* Trace outbound HTTP requests */ int fHttpSecure; /* Encrypt sync traffic */ int fNoSync; /* Do not do an autosync even. --nosync */ char *zPath; /* Name of webpage being served */ char *zExtra; /* Extra path information past the webpage name */ char *zBaseURL; /* Full text of the URL being served */ char *zTop; /* Parent directory of zPath */ const char *zContentType; /* The content type of the input HTTP request */ int iErrPriority; /* Priority of current error message */ |
| ︙ | ︙ |