Fossil

Check-in [776753118f]
Login

Check-in [776753118f]

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

Overview
Comment:The nonce of a login card in the sync protocol is now the SHA1 hash of the remainder of the sync message. The signature is the SHA1 hash of the concatenation of the nonce and the users password.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 776753118f1bafcab5b2867aeec5a6c0dacea765
User & Date: drh 2007-09-12 02:25:37.000
Context
2007-09-13
03:52
Improvements to the CLI timeline display. When an update fails due to multiple descendents, show all of the descendents in timeline format. ... (check-in: fcabd4774c user: drh tags: trunk)
2007-09-12
02:25
The nonce of a login card in the sync protocol is now the SHA1 hash of the remainder of the sync message. The signature is the SHA1 hash of the concatenation of the nonce and the users password. ... (check-in: 776753118f user: drh tags: trunk)
01:46
Fix bugs in undo/redo. Appears to work now but not heavily tested. ... (check-in: 6f5654c7ab user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/http.c.
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  Blob login, nonce, sig, pw, payload, hdr;
  const char *zSep;
  int i;
  int cnt = 0;

  blob_zero(&nonce);
  blob_zero(&pw);
  db_blob(&nonce, "SELECT hex(randomblob(20))");
  blob_copy(&pw, &nonce);
  blob_zero(&login);
  if( g.urlUser==0 ){
    user_select();
    db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
    sha1sum_blob(&pw, &sig);
    blob_appendf(&login, "login %s %b %b\n", g.zLogin, &nonce, &sig);







|







165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
  Blob login, nonce, sig, pw, payload, hdr;
  const char *zSep;
  int i;
  int cnt = 0;

  blob_zero(&nonce);
  blob_zero(&pw);
  sha1sum_blob(pSend, &nonce);
  blob_copy(&pw, &nonce);
  blob_zero(&login);
  if( g.urlUser==0 ){
    user_select();
    db_blob(&pw, "SELECT pw FROM user WHERE uid=%d", g.userUid);
    sha1sum_blob(&pw, &sig);
    blob_appendf(&login, "login %s %b %b\n", g.zLogin, &nonce, &sig);
Changes to src/xfer.c.
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
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
    const char *zUuid = db_column_text(&q, 0);
    blob_appendf(pXfer->pOut, "gimme %s\n", zUuid);
    pXfer->nGimmeSent++;
  }
  db_finalize(&q);
}



















/*
** Check the signature on an application/x-fossil payload received by
** the HTTP server.  The signature is a line of the following form:
**
**        login LOGIN NONCE SIGNATURE
**
** The NONCE is a random string.  The server will never accept a
** repeat NONCE.  SIGNATURE is the SHA1 checksum of the NONCE 
** concatenated with the users password.
**
** The parameters to this routine are ephermeral blobs holding the
** LOGIN, NONCE and SIGNATURE.
**
** This routine attempts to locate the user and verify the signature.
** If everything checks out, the USER.CAP column for the USER table
** is consulted to set privileges in the global g variable.
**
** If anything fails to check out, no changes are made to privileges.
**
** Signature generation on the client side is handled by the 
** http_exchange() routine.
*/
void check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
  Stmt q;
  int rc;

  if( db_exists("SELECT 1 FROM rcvfrom WHERE nonce=%B", pNonce) ){
    return;  /* Never accept a repeated nonce */
  }
  db_prepare(&q, "SELECT pw, cap, uid FROM user WHERE login=%B", pLogin);
  if( db_step(&q)==SQLITE_ROW ){
    Blob pw, combined, hash;
    blob_zero(&pw);
    db_ephemeral_blob(&q, 0, &pw);
    blob_zero(&combined);
    blob_copy(&combined, pNonce);







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







|
|
|

















<
<
<







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
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295



296
297
298
299
300
301
302
    const char *zUuid = db_column_text(&q, 0);
    blob_appendf(pXfer->pOut, "gimme %s\n", zUuid);
    pXfer->nGimmeSent++;
  }
  db_finalize(&q);
}

/*
** Compute an SHA1 hash on the tail of pMsg.  Verify that it matches the
** the hash given in pHash.  Return 1 on a successful match.  Return 0
** if there is a mismatch.
*/
static int check_tail_hash(Blob *pHash, Blob *pMsg){
  Blob tail;
  Blob h2;
  int rc;
  blob_tail(pMsg, &tail);
  sha1sum_blob(&tail, &h2);
  rc = blob_compare(pHash, &h2);
  blob_reset(&h2);
  blob_reset(&tail);
  return rc==0;
}


/*
** Check the signature on an application/x-fossil payload received by
** the HTTP server.  The signature is a line of the following form:
**
**        login LOGIN NONCE SIGNATURE
**
** The NONCE is the SHA1 hash of the remainder of the input.  
** SIGNATURE is the SHA1 checksum of the NONCE concatenated 
** with the users password.
**
** The parameters to this routine are ephermeral blobs holding the
** LOGIN, NONCE and SIGNATURE.
**
** This routine attempts to locate the user and verify the signature.
** If everything checks out, the USER.CAP column for the USER table
** is consulted to set privileges in the global g variable.
**
** If anything fails to check out, no changes are made to privileges.
**
** Signature generation on the client side is handled by the 
** http_exchange() routine.
*/
void check_login(Blob *pLogin, Blob *pNonce, Blob *pSig){
  Stmt q;
  int rc;




  db_prepare(&q, "SELECT pw, cap, uid FROM user WHERE login=%B", pLogin);
  if( db_step(&q)==SQLITE_ROW ){
    Blob pw, combined, hash;
    blob_zero(&pw);
    db_ephemeral_blob(&q, 0, &pw);
    blob_zero(&combined);
    blob_copy(&combined, pNonce);
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
    ** The client can send multiple logins.  Permissions are cumulative.
    */
    if( blob_eq(&xfer.aToken[0], "login")
     && xfer.nToken==4
    ){
      if( disableLogin ){
        g.okRead = g.okWrite = 1;
      }else{
        check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3]);
      }
    }else
    
    /*    cookie TEXT
    **
    ** A cookie contains a arbitrary-length argument that is server-defined.







|







548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
    ** The client can send multiple logins.  Permissions are cumulative.
    */
    if( blob_eq(&xfer.aToken[0], "login")
     && xfer.nToken==4
    ){
      if( disableLogin ){
        g.okRead = g.okWrite = 1;
      }else if( check_tail_hash(&xfer.aToken[2], xfer.pIn) ){
        check_login(&xfer.aToken[1], &xfer.aToken[2], &xfer.aToken[3]);
      }
    }else
    
    /*    cookie TEXT
    **
    ** A cookie contains a arbitrary-length argument that is server-defined.
Changes to www/sync.html.
118
119
120
121
122
123
124
125

126

127
128

129
130
131
132
133
134
135
136
137
cards.  Each login card has the following format:</p>

<blockquote>
<b>login</b>  <i>userid  nonce  signature</i>
</blockquote>

<p>The userid is the name of the user that is requesting service
from the server.  The nonce is a random one-use hexadecimal number.

The signature is the SHA1 hash of the users password.</p>


<p>For each login card, the server looks up the user and verifies

that the nonce has never before been used.  It then checks the
signature hash to make sure the signature matches.  If everything
checks out, then the client is granted all privileges of the
specified user.</p>

<p>Privileges are cumulative.  There can be multiple successful
login cards.  The session privileges are the bit-wise OR of the
privileges of each individual login.</p>








|
>
|
>


>
|
|







118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
cards.  Each login card has the following format:</p>

<blockquote>
<b>login</b>  <i>userid  nonce  signature</i>
</blockquote>

<p>The userid is the name of the user that is requesting service
from the server.  The nonce is the SHA1 hash of the remainder of
the message - all text that follows the newline character that
terminates the login card.  The signature is the SHA1 hash of
the concatenation of the nonce and the users password.</p>

<p>For each login card, the server looks up the user and verifies
that the nonce matches the SHA1 hash of the remainder of the
message.  It then checks the signature hash to make sure the 
signature matches.  If everything
checks out, then the client is granted all privileges of the
specified user.</p>

<p>Privileges are cumulative.  There can be multiple successful
login cards.  The session privileges are the bit-wise OR of the
privileges of each individual login.</p>