Althttpd

Check-in [0a03b61432]
Login

Check-in [0a03b61432]

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

Overview
Comment:Removed manual tracking of SSL is-EOF (unnecessary), call Malfunction() if tls_gets() fails, and remove dangling tls_close_conn() calls after Redirect() calls, as those broke TLS redirects.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 0a03b61432d418371ce5be31d775dc062db6868017d4087669600b271844f10b
User & Date: stephan 2022-01-16 03:25:22
Original Comment: Removed manual tracking of SSL is-EOF (unnecessary), call Malfunction() if tls_gets() fails, and remove dangling tls_close_conn() calls after redirects which broke HTTPS redirects.
Context
2022-01-16
12:06
Make the default version number 2.0, even if the version number is not set by the Makefile. Avoid an unnecessary memory allocation. ... (check-in: da83441048 user: drh tags: trunk)
03:25
Removed manual tracking of SSL is-EOF (unnecessary), call Malfunction() if tls_gets() fails, and remove dangling tls_close_conn() calls after Redirect() calls, as those broke TLS redirects. ... (check-in: 0a03b61432 user: stephan tags: trunk)
02:58
Default zHttpScheme to "http" so that redirects from /dir/ to /dir/index work in HTTP mode. Those same redirects in HTTPS are breaking with SSL errors ("invalid response") with or without this change. ... (check-in: f89d874075 user: stephan tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to althttpd.c.

374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/x509.h>
typedef struct TlsServerConn {
  SSL *ssl;          /* The SSL codec */
  BIO *bio;          /* SSL BIO object */
  int atEof;         /* True when EOF reached. */
  int iSocket;       /* The socket */
} TlsServerConn;

/*
** There can only be a single OpenSSL IO connection open at a time.
** State information about that IO is stored in the following
** local variables:







<







374
375
376
377
378
379
380

381
382
383
384
385
386
387
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/x509.h>
typedef struct TlsServerConn {
  SSL *ssl;          /* The SSL codec */
  BIO *bio;          /* SSL BIO object */

  int iSocket;       /* The socket */
} TlsServerConn;

/*
** There can only be a single OpenSSL IO connection open at a time.
** State information about that IO is stored in the following
** local variables:
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
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
  NULL,                   /* zCertFile */
  NULL,                   /* zKeyFile */
  NULL                    /* sslCon */
};

/*
** Read a single line of text from the client and stores it in zBuf
** (which must be at least nBuf bytes long). At EOF it sets
** tlsState.sslCon->atEof to non-0 and returns 0.  On error simply
** returns 0. Once tlsState.sslCon->atEof is non-0, subsequent calls
** to this function return 0 without reading anything.
**
** If it reads anything, it returns zBuf.
*/
static char *tls_gets(void *pServerArg, char *zBuf, int nBuf){
  int n = 0;
  int i;
  TlsServerConn * const pServer = (TlsServerConn*)pServerArg;
  if( pServer->atEof ) return 0;
  for(i=0; i<nBuf-1; i++){
    n = SSL_read(pServer->ssl, &zBuf[i], 1);

    if( n<=0 ){
      pServer->atEof = 1;


      return 0;
    }
    if( zBuf[i]=='\n' ) break;
  }
  zBuf[i+1] = 0;
  return zBuf;
}

/*
** Reads up tp nBuf bytes of TLS-decoded bytes from the client and
** stores them in zBuf, which must be least nBuf bytes long.  Returns
** the number of bytes read. Fails fatally if nBuf is "too big" or if
** SSL_read() fails. Once pServerArg reaches EOF, this function simply
** returns 0 with no side effects.
*/
static size_t tls_read_server(void *pServerArg, void *zBuf, size_t nBuf){
  int err = 0;
  size_t rc = 0;
  TlsServerConn * const pServer = (TlsServerConn*)pServerArg;
  if( nBuf>0x7fffffff ){
    Malfunction(500,"SSL read too big");
  }
  while( 0==err && nBuf!=rc && 0==pServer->atEof ){
    const int n = SSL_read(pServer->ssl, zBuf + rc, (int)(nBuf - rc));
    if( n==0 ){
      pServer->atEof = 1;
      break;
    }
    err = SSL_get_error(pServer->ssl, n);
    if(0==err){
      rc += n;
      pServer->atEof = BIO_eof(pServer->bio);
    }else{
      Malfunction(500,"SSL read error.");
    }
  }
  return rc;
}








|
<
<
|




|


|


>
|
<
>
>
|

<



















|


<





<







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
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444

445
446
447
448
449

450
451
452
453
454
455
456
  NULL,                   /* zCertFile */
  NULL,                   /* zKeyFile */
  NULL                    /* sslCon */
};

/*
** Read a single line of text from the client and stores it in zBuf
** (which must be at least nBuf bytes long). On error it


** calls Malfunction().
**
** If it reads anything, it returns zBuf.
*/
static char *tls_gets(void *pServerArg, char *zBuf, int nBuf){
  int n = 0, err = 0;
  int i;
  TlsServerConn * const pServer = (TlsServerConn*)pServerArg;
  if( BIO_eof(pServer->bio) ) return 0;
  for(i=0; i<nBuf-1; i++){
    n = SSL_read(pServer->ssl, &zBuf[i], 1);
    err = SSL_get_error(pServer->ssl, n);
    if( err!=0 ){

      Malfunction(500,"SSL read error.");
    }else if( 0==n || zBuf[i]=='\n' ){
      break;
    }

  }
  zBuf[i+1] = 0;
  return zBuf;
}

/*
** Reads up tp nBuf bytes of TLS-decoded bytes from the client and
** stores them in zBuf, which must be least nBuf bytes long.  Returns
** the number of bytes read. Fails fatally if nBuf is "too big" or if
** SSL_read() fails. Once pServerArg reaches EOF, this function simply
** returns 0 with no side effects.
*/
static size_t tls_read_server(void *pServerArg, void *zBuf, size_t nBuf){
  int err = 0;
  size_t rc = 0;
  TlsServerConn * const pServer = (TlsServerConn*)pServerArg;
  if( nBuf>0x7fffffff ){
    Malfunction(500,"SSL read too big");
  }
  while( 0==err && nBuf!=rc && 0==BIO_eof(pServer->bio) ){
    const int n = SSL_read(pServer->ssl, zBuf + rc, (int)(nBuf - rc));
    if( n==0 ){

      break;
    }
    err = SSL_get_error(pServer->ssl, n);
    if(0==err){
      rc += n;

    }else{
      Malfunction(500,"SSL read error.");
    }
  }
  return rc;
}

1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
  TlsServerConn *pServer = malloc(sizeof(*pServer));
  BIO *b = pServer ? BIO_new_socket(iSocket, 0) : NULL;
  if( NULL==b ){
    Malfunction(500,"Cannot allocate TlsServerConn.");
  }
  assert(NULL!=tlsState.ctx);
  pServer->ssl = SSL_new(tlsState.ctx);
  pServer->atEof = 0;
  pServer->bio = b;
  pServer->iSocket = iSocket;
  SSL_set_bio(pServer->ssl, b, b);
  SSL_accept(pServer->ssl);
  return (void*)pServer;
}








<







1636
1637
1638
1639
1640
1641
1642

1643
1644
1645
1646
1647
1648
1649
  TlsServerConn *pServer = malloc(sizeof(*pServer));
  BIO *b = pServer ? BIO_new_socket(iSocket, 0) : NULL;
  if( NULL==b ){
    Malfunction(500,"Cannot allocate TlsServerConn.");
  }
  assert(NULL!=tlsState.ctx);
  pServer->ssl = SSL_new(tlsState.ctx);

  pServer->bio = b;
  pServer->iSocket = iSocket;
  SSL_set_bio(pServer->ssl, b, b);
  SSL_accept(pServer->ssl);
  return (void*)pServer;
}

2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
      while( stillSearching && i>0 && j>j0 ){
        while( j>j0 && zLine[j-1]!='/' ){ j--; }
        strcpy(&zLine[j-1], "/not-found.html");
        if( stat(zLine,&statbuf)==0 && S_ISREG(statbuf.st_mode)
            && access(zLine,R_OK)==0 ){
          zRealScript = StrDup(&zLine[j0]);
          Redirect(zRealScript, 302, 1, 370); /* LOG: redirect to not-found */
          tls_close_conn();
          return;
        }else{
          j--;
        }
      }
      if( stillSearching ) NotFound(380); /* LOG: URI not found */
      break;







<







2555
2556
2557
2558
2559
2560
2561

2562
2563
2564
2565
2566
2567
2568
      while( stillSearching && i>0 && j>j0 ){
        while( j>j0 && zLine[j-1]!='/' ){ j--; }
        strcpy(&zLine[j-1], "/not-found.html");
        if( stat(zLine,&statbuf)==0 && S_ISREG(statbuf.st_mode)
            && access(zLine,R_OK)==0 ){
          zRealScript = StrDup(&zLine[j0]);
          Redirect(zRealScript, 302, 1, 370); /* LOG: redirect to not-found */

          return;
        }else{
          j--;
        }
      }
      if( stillSearching ) NotFound(380); /* LOG: URI not found */
      break;
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
      zRealScript = StrDup(&zLine[j0]);
      if( zScript[i]==0 ){
        /* If the requested URL does not end with "/" but we had to
        ** append "index.html", then a redirect is necessary.  Otherwise
        ** none of the relative URLs in the delivered document will be
        ** correct. */
        Redirect(zRealScript,301,1,410); /* LOG: redirect to add trailing / */
        tls_close_conn();
        return;
      }
      break;
    }
    zLine[j] = zScript[i];
    i++; j++;
  }







<







2591
2592
2593
2594
2595
2596
2597

2598
2599
2600
2601
2602
2603
2604
      zRealScript = StrDup(&zLine[j0]);
      if( zScript[i]==0 ){
        /* If the requested URL does not end with "/" but we had to
        ** append "index.html", then a redirect is necessary.  Otherwise
        ** none of the relative URLs in the delivered document will be
        ** correct. */
        Redirect(zRealScript,301,1,410); /* LOG: redirect to add trailing / */

        return;
      }
      break;
    }
    zLine[j] = zScript[i];
    i++; j++;
  }