Check-in [0554dbd04a]
Not logged in

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

Overview
Comment:Merge the ssl-trust-fix branch into trunk.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:0554dbd04a751da15ec98267f4af2f10769a3c36
User & Date: drh 2011-10-10 11:38:50
Context
2011-10-10
12:55
Fix indentation and formatting in http_ssl.c. Limit line length to 80 characters per the coding style spec. check-in: 5eb8f0157a user: drh tags: trunk
11:38
Merge the ssl-trust-fix branch into trunk. check-in: 0554dbd04a user: drh tags: trunk
08:56
Fix constant prompting on already saved SSL certificates that are not trusted for some reason (e.g. host mismatch, etc). Closed-Leaf check-in: 25169506b7 user: mistachkin tags: ssl-trust-fix
2011-10-07
19:55
Documentation update. check-in: c0b6c28d29 user: drh tags: trunk
Changes

Changes to src/http_ssl.c.

182
183
184
185
186
187
188

189
190
191
192
193
194
195
196
197
198
199
200
201
202
...
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
...
276
277
278
279
280
281
282




283

284
285
286
287
288
289
290
...
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
330
331
332







333
334
335
336
337
338
339
**    g.urlPort       TCP/IP port to use.  Ex: 80
**
** Return the number of errors.
*/
int ssl_open(void){
  X509 *cert;
  int hasSavedCertificate = 0;

char *connStr ;
  ssl_global_init();

  /* Get certificate for current server from global config and
   * (if we have it in config) add it to certificate store.
   */
  cert = ssl_get_certificate();
  if ( cert!=NULL ){
    X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert);
    X509_free(cert);
    hasSavedCertificate = 1;
  }

  iBio = BIO_new_ssl_connect(sslCtx);
................................................................................

  if ( cert==NULL ){
    ssl_set_errmsg("No SSL certificate was presented by the peer");
    ssl_close();
    return 1;
  }

  if( SSL_get_verify_result(ssl) != X509_V_OK ){
    char *desc, *prompt;
    char *warning = "";
    Blob ans;
    BIO *mem;
    unsigned char md[32];
    unsigned int mdLength = 31;
    
................................................................................
    if( blob_str(&ans)[0]!='y' && blob_str(&ans)[0]!='a' ) {
      X509_free(cert);
      ssl_set_errmsg("SSL certificate declined");
      ssl_close();
      return 1;
    }
    if( blob_str(&ans)[0]=='a' ) {




      ssl_save_certificate(cert);

    }
    blob_reset(&ans);
  }

  /* Set the Global.zIpAddr variable to the server we are talking to.
  ** This is used to populate the ipaddr column of the rcvfrom table,
  ** if any files are received from the server.
................................................................................
  X509_free(cert);
  return 0;
}

/*
** Save certificate to global config.
*/
void ssl_save_certificate(X509 *cert){
  BIO *mem;
  char *zCert, *zHost;

  mem = BIO_new(BIO_s_mem());
  PEM_write_bio_X509(mem, cert);
  BIO_write(mem, "", 1); /* nul-terminate mem buffer */
  BIO_get_mem_data(mem, &zCert);
  zHost = mprintf("cert:%s", g.urlName);
  db_set(zHost, zCert, 1);
  free(zHost);



  BIO_free(mem);  
}

/*
** Get certificate for g.urlName from global config.
** Return NULL if no certificate found.
*/
X509 *ssl_get_certificate(void){
  char *zHost, *zCert;
  BIO *mem;
  X509 *cert;

  zHost = mprintf("cert:%s", g.urlName);
  zCert = db_get(zHost, NULL);
  free(zHost);
  if ( zCert==NULL )
    return NULL;







  mem = BIO_new(BIO_s_mem());
  BIO_puts(mem, zCert);
  cert = PEM_read_bio_X509(mem, NULL, 0, NULL);
  free(zCert);
  BIO_free(mem);  
  return cert;
}







>






|







 







|







 







>
>
>
>
|
>







 







|










>
>
>







|









>
>
>
>
>
>
>







182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
...
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
...
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
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
**    g.urlPort       TCP/IP port to use.  Ex: 80
**
** Return the number of errors.
*/
int ssl_open(void){
  X509 *cert;
  int hasSavedCertificate = 0;
  int trusted = 0;
char *connStr ;
  ssl_global_init();

  /* Get certificate for current server from global config and
   * (if we have it in config) add it to certificate store.
   */
  cert = ssl_get_certificate(&trusted);
  if ( cert!=NULL ){
    X509_STORE_add_cert(SSL_CTX_get_cert_store(sslCtx), cert);
    X509_free(cert);
    hasSavedCertificate = 1;
  }

  iBio = BIO_new_ssl_connect(sslCtx);
................................................................................

  if ( cert==NULL ){
    ssl_set_errmsg("No SSL certificate was presented by the peer");
    ssl_close();
    return 1;
  }

  if( trusted<=0 && SSL_get_verify_result(ssl) != X509_V_OK ){
    char *desc, *prompt;
    char *warning = "";
    Blob ans;
    BIO *mem;
    unsigned char md[32];
    unsigned int mdLength = 31;
    
................................................................................
    if( blob_str(&ans)[0]!='y' && blob_str(&ans)[0]!='a' ) {
      X509_free(cert);
      ssl_set_errmsg("SSL certificate declined");
      ssl_close();
      return 1;
    }
    if( blob_str(&ans)[0]=='a' ) {
      Blob ans2;
      prompt_user("\nSave this certificate as fully trusted [a=always/N]? ",
                  &ans2);
      trusted = (blob_str(&ans2)[0]=='a');
      ssl_save_certificate(cert, trusted);
      blob_reset(&ans2);
    }
    blob_reset(&ans);
  }

  /* Set the Global.zIpAddr variable to the server we are talking to.
  ** This is used to populate the ipaddr column of the rcvfrom table,
  ** if any files are received from the server.
................................................................................
  X509_free(cert);
  return 0;
}

/*
** Save certificate to global config.
*/
void ssl_save_certificate(X509 *cert, int trusted){
  BIO *mem;
  char *zCert, *zHost;

  mem = BIO_new(BIO_s_mem());
  PEM_write_bio_X509(mem, cert);
  BIO_write(mem, "", 1); /* nul-terminate mem buffer */
  BIO_get_mem_data(mem, &zCert);
  zHost = mprintf("cert:%s", g.urlName);
  db_set(zHost, zCert, 1);
  free(zHost);
  zHost = mprintf("trusted:%s", g.urlName);
  db_set_int(zHost, trusted, 1);
  free(zHost);
  BIO_free(mem);  
}

/*
** Get certificate for g.urlName from global config.
** Return NULL if no certificate found.
*/
X509 *ssl_get_certificate(int *pTrusted){
  char *zHost, *zCert;
  BIO *mem;
  X509 *cert;

  zHost = mprintf("cert:%s", g.urlName);
  zCert = db_get(zHost, NULL);
  free(zHost);
  if ( zCert==NULL )
    return NULL;

  if ( pTrusted!=0 ){
    zHost = mprintf("trusted:%s", g.urlName);
    *pTrusted = db_get_int(zHost, 0);
    free(zHost);
  }

  mem = BIO_new(BIO_s_mem());
  BIO_puts(mem, zCert);
  cert = PEM_read_bio_X509(mem, NULL, 0, NULL);
  free(zCert);
  BIO_free(mem);  
  return cert;
}