Fossil

Check-in [1a1aa98a40]
Login

Check-in [1a1aa98a40]

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

Overview
Comment:Use the new certificate bundle management for https connections, and deactivate the old environment variable code. Added support for specifying certificate/key bundle to clone/push/pull/sync commands.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | jan-clientcert
Files: files | file ages | folders
SHA1: 1a1aa98a4091d6552e0645dfaa9e44fbb8887883
User & Date: jan 2011-03-30 18:49:23.265
Context
2011-03-30
20:58
Fix two potential SQL injection attacks. ... (check-in: 71384ce668 user: drh tags: jan-clientcert)
18:49
Use the new certificate bundle management for https connections, and deactivate the old environment variable code. Added support for specifying certificate/key bundle to clone/push/pull/sync commands. ... (check-in: 1a1aa98a40 user: jan tags: jan-clientcert)
15:40
Added a 'cert' subcommand to manage certificate groups, and added a certificate table to the global db. Minor code formatting change. ... (check-in: 1156ad25db user: jan tags: jan-clientcert)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/clone.c.
35
36
37
38
39
40
41


42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
** admin user. This can be overridden using the -A|--admin-user
** parameter.
**
** Options:
**
**    --admin-user|-A USERNAME    Make USERNAME the administrator
**    --private                   Also clone private branches 


**
*/
void clone_cmd(void){
  char *zPassword;
  const char *zDefaultUser;   /* Optional name of the default user */
  int nErr = 0;
  int bPrivate;               /* Also clone private branches */

  bPrivate = find_option("private",0,0)!=0;

  url_proxy_options();
  if( g.argc < 4 ){
    usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
  }
  db_open_config(0);
  if( file_size(g.argv[3])>0 ){
    fossil_panic("file already exists: %s", g.argv[3]);







>
>









>







35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
** admin user. This can be overridden using the -A|--admin-user
** parameter.
**
** Options:
**
**    --admin-user|-A USERNAME    Make USERNAME the administrator
**    --private                   Also clone private branches 
**    --certgroup NAME            Use certificate group NAME for https
**                                connections
**
*/
void clone_cmd(void){
  char *zPassword;
  const char *zDefaultUser;   /* Optional name of the default user */
  int nErr = 0;
  int bPrivate;               /* Also clone private branches */

  bPrivate = find_option("private",0,0)!=0;
  g.urlCertGroup = find_option("certgroup",0,1);
  url_proxy_options();
  if( g.argc < 4 ){
    usage("?OPTIONS? FILE-OR-URL NEW-REPOSITORY");
  }
  db_open_config(0);
  if( file_size(g.argv[3])>0 ){
    fossil_panic("file already exists: %s", g.argv[3]);
Changes to src/http_ssl.c.
287
288
289
290
291
292
293

294
295
296
297
298
299
300
    total += got;
    N -= got;
    pContent = (void*)&((char*)pContent)[got];
  }
  return total;
}


/*
** Read client certificate and key, if set, and store them in the SSL context
** to allow communication with servers which are configured to verify client
** certificates and certificate chains.
** We only support PEM and don't support password protected keys.
**
** Always try the environment variables first, and if they aren't set, then







>







287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
    total += got;
    N -= got;
    pContent = (void*)&((char*)pContent)[got];
  }
  return total;
}

#if 0
/*
** Read client certificate and key, if set, and store them in the SSL context
** to allow communication with servers which are configured to verify client
** certificates and certificate chains.
** We only support PEM and don't support password protected keys.
**
** Always try the environment variables first, and if they aren't set, then
350
351
352
353
354
355
356

357












































































358
359
360
361
362
363
364
  }

  free(keyfile);
  free(certfile);
  free(capath);
  free(cafile);
}














































































/*
** Get SSL authentication file reference from environment variable. If set,
** then store varaible in global config. If environment variable was not set,
** attempt to get variable from global config.
**/
char *ssl_get_and_set_file_ref(const char *envvar, const char *dbvar){
  char *zVar;







>

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







351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
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
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
  }

  free(keyfile);
  free(certfile);
  free(capath);
  free(cafile);
}
#endif

/*
** If an certgroup has been specified on the command line, then use it to look
** up certificates and keys, and then store the URL-certgroup association in
** the global database. If no certgroup has been specified on the command line,
** see if there's an entry for the url in global_config, and use it if
** applicable.
*/
void ssl_load_client_authfiles(void){
  char *zGroupName = NULL;
  char *cafile;
  char *capath;
  char *certfile;
  char *keyfile;

  if( g.urlCertGroup ){
    char *zName;
    zName = mprintf("certgroup:%s", g.urlName);
    db_set(zName, g.urlCertGroup, 1);
    free(zName);
    zGroupName = strdup(g.urlCertGroup);
  }else{
    db_swap_connections();
    zGroupName = db_text(0, "SELECT value FROM global_config"
                            " WHERE name='certgroup:%q'", g.urlName);
    db_swap_connections();
  }
  if( !zGroupName ){
    /* No cert group specified or found cached */
    return;
  }

  db_swap_connections();
  cafile = db_text(0, "SELECT filepath FROM certs WHERE name=%Q"
                      " AND type='cafile'", zGroupName);
  capath = db_text(0, "SELECT filepath FROM certs WHERE name=%Q"
                      " AND type='capath'", zGroupName);
  db_swap_connections();

  if( cafile || capath ){
    /* The OpenSSL documentation warns that if several CA certificates match
    ** the same name, key identifier and serial number conditions, only the
    ** first will be examined. The caveat situation occurs when one stores an
    ** expired CA certificate among the valid ones.
    ** Simply put: Do not mix expired and valid certificates.
    */
    if( SSL_CTX_load_verify_locations(sslCtx, cafile, capath)==0 ){
      fossil_fatal("SSL: Unable to load CA verification file/path");
    }
  }

  db_swap_connections();
  keyfile = db_text(0, "SELECT filepath FROM certs WHERE name=%Q"
                       " AND type='ckey'", zGroupName);
  certfile = db_text(0, "SELECT filepath FROM certs WHERE name=%Q"
                        " AND type='ccert'", zGroupName);
  db_swap_connections();

  if( SSL_CTX_use_certificate_file(sslCtx, certfile, SSL_FILETYPE_PEM)<=0 ){
    fossil_fatal("SSL: Unable to open client certificate in %s.", certfile);
  }
  if( SSL_CTX_use_PrivateKey_file(sslCtx, keyfile, SSL_FILETYPE_PEM)<=0 ){
    fossil_fatal("SSL: Unable to open client key in %s.", keyfile);
  }

  if( !SSL_CTX_check_private_key(sslCtx) ){
    fossil_fatal("SSL: Private key does not match the certificate public "
        "key.");
  }

  free(keyfile);
  free(certfile);
  free(capath);
  free(cafile);
}

#if 0
/*
** Get SSL authentication file reference from environment variable. If set,
** then store varaible in global config. If environment variable was not set,
** attempt to get variable from global config.
**/
char *ssl_get_and_set_file_ref(const char *envvar, const char *dbvar){
  char *zVar;
376
377
378
379
380
381
382

383
384
385
386
387
388
389
  }else{
    zVar = db_get(zTmp, NULL);
  }
  free(zTmp);

  return zVar;
}


/*
** COMMAND: cert
**
** Usage: %fossil cert SUBCOMMAND ...
**
** Manage/group PKI keys/certificates to be able to use client







>







454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
  }else{
    zVar = db_get(zTmp, NULL);
  }
  free(zTmp);

  return zVar;
}
#endif

/*
** COMMAND: cert
**
** Usage: %fossil cert SUBCOMMAND ...
**
** Manage/group PKI keys/certificates to be able to use client
406
407
408
409
410
411
412

413
414
415
416
417
418
419
**
**        Disassociate URL from any credential group(s).
**
**    %fossil cert delete NAME
**
**        Remove the credential group NAME and all it's associated URL
**        associations.

*/
void cert_cmd(void){
  int n;
  const char *zCmd = "list";
  if( g.argc>=3 ){
    zCmd = g.argv[2];
  }







>







485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
**
**        Disassociate URL from any credential group(s).
**
**    %fossil cert delete NAME
**
**        Remove the credential group NAME and all it's associated URL
**        associations.
**
*/
void cert_cmd(void){
  int n;
  const char *zCmd = "list";
  if( g.argc>=3 ){
    zCmd = g.argv[2];
  }
Changes to src/main.c.
100
101
102
103
104
105
106

107
108
109
110
111
112
113
  char *urlPath;          /* Pathname for http: */
  char *urlUser;          /* User id for http: */
  char *urlPasswd;        /* Password for http: */
  char *urlCanonical;     /* Canonical representation of the URL */
  char *urlProxyAuth;     /* Proxy-Authorizer: string */
  char *urlFossil;        /* The path of the ?fossil=path suffix on ssh: */
  int dontKeepUrl;        /* Do not persist the URL */


  const char *zLogin;     /* Login name.  "" if not logged in. */
  int useLocalauth;       /* No login required if from 127.0.0.1 */
  int noPswd;             /* Logged in without password (on 127.0.0.1) */
  int userUid;            /* Integer user id */

  /* Information used to populate the RCVFROM table */







>







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  char *urlPath;          /* Pathname for http: */
  char *urlUser;          /* User id for http: */
  char *urlPasswd;        /* Password for http: */
  char *urlCanonical;     /* Canonical representation of the URL */
  char *urlProxyAuth;     /* Proxy-Authorizer: string */
  char *urlFossil;        /* The path of the ?fossil=path suffix on ssh: */
  int dontKeepUrl;        /* Do not persist the URL */
  const char *urlCertGroup; /* Which ceritificate group to use for URL */

  const char *zLogin;     /* Login name.  "" if not logged in. */
  int useLocalauth;       /* No login required if from 127.0.0.1 */
  int noPswd;             /* Logged in without password (on 127.0.0.1) */
  int userUid;            /* Integer user id */

  /* Information used to populate the RCVFROM table */
Changes to src/sync.c.
94
95
96
97
98
99
100

101
102
103
104
105
106
107
static void process_sync_args(int *pConfigSync, int *pPrivate){
  const char *zUrl = 0;
  const char *zPw = 0;
  int configSync = 0;
  int urlOptional = find_option("autourl",0,0)!=0;
  g.dontKeepUrl = find_option("once",0,0)!=0;
  *pPrivate = find_option("private",0,0)!=0;

  url_proxy_options();
  db_find_and_open_repository(0, 0);
  db_open_config(0);
  if( g.argc==2 ){
    zUrl = db_get("last-sync-url", 0);
    zPw = unobscure(db_get("last-sync-pw", 0));
    if( db_get_boolean("auto-sync",1) ) configSync = CONFIGSET_SHUN;







>







94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
static void process_sync_args(int *pConfigSync, int *pPrivate){
  const char *zUrl = 0;
  const char *zPw = 0;
  int configSync = 0;
  int urlOptional = find_option("autourl",0,0)!=0;
  g.dontKeepUrl = find_option("once",0,0)!=0;
  *pPrivate = find_option("private",0,0)!=0;
  g.urlCertGroup = find_option("certgroup",0,1);
  url_proxy_options();
  db_find_and_open_repository(0, 0);
  db_open_config(0);
  if( g.argc==2 ){
    zUrl = db_get("last-sync-url", 0);
    zPw = unobscure(db_get("last-sync-pw", 0));
    if( db_get_boolean("auto-sync",1) ) configSync = CONFIGSET_SHUN;
148
149
150
151
152
153
154





155
156
157
158
159
160
161
162
** subsequent push, pull, and sync operations.  However, the "--once"
** command-line option makes the URL a one-time-use URL that is not
** saved.
**
** Use the --private option to pull private branches from the
** remote repository.
**





** See also: clone, push, sync, remote-url
*/
void pull_cmd(void){
  int syncFlags;
  int bPrivate;
  process_sync_args(&syncFlags, &bPrivate);
  client_sync(0,1,0,bPrivate,syncFlags,0);
}







>
>
>
>
>
|







149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
** subsequent push, pull, and sync operations.  However, the "--once"
** command-line option makes the URL a one-time-use URL that is not
** saved.
**
** Use the --private option to pull private branches from the
** remote repository.
**
** Use the "--certgroup NAME" option to specify the name of the
** certificate/key bundle to use for https connections. If this option
** is not specified, a cached value associated with the URL will be
** used if it exists.
**
** See also: cert, clone, push, sync, remote-url
*/
void pull_cmd(void){
  int syncFlags;
  int bPrivate;
  process_sync_args(&syncFlags, &bPrivate);
  client_sync(0,1,0,bPrivate,syncFlags,0);
}
177
178
179
180
181
182
183





184
185
186
187
188
189
190
191
** subsequent push, pull, and sync operations.  However, the "--once"
** command-line option makes the URL a one-time-use URL that is not
** saved.
**
** Use the --private option to push private branches to the
** remote repository.
**





** See also: clone, pull, sync, remote-url
*/
void push_cmd(void){
  int syncFlags;
  int bPrivate;
  process_sync_args(&syncFlags, &bPrivate);
  client_sync(1,0,0,bPrivate,0,0);
}







>
>
>
>
>
|







183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
** subsequent push, pull, and sync operations.  However, the "--once"
** command-line option makes the URL a one-time-use URL that is not
** saved.
**
** Use the --private option to push private branches to the
** remote repository.
**
** Use the "--certgroup NAME" option to specify the name of the
** certificate/key bundle to use for https connections. If this option
** is not specified, a cached value associated with the URL will be
** used if it exists.
**
** See also: cert, clone, pull, sync, remote-url
*/
void push_cmd(void){
  int syncFlags;
  int bPrivate;
  process_sync_args(&syncFlags, &bPrivate);
  client_sync(1,0,0,bPrivate,0,0);
}
212
213
214
215
216
217
218





219
220
221
222
223
224
225
226
** subsequent push, pull, and sync operations.  However, the "--once"
** command-line option makes the URL a one-time-use URL that is not
** saved.
**
** Use the --private option to sync private branches with the
** remote repository.
**





** See also:  clone, push, pull, remote-url
*/
void sync_cmd(void){
  int syncFlags;
  int bPrivate;
  process_sync_args(&syncFlags, &bPrivate);
  client_sync(1,1,0,bPrivate,syncFlags,0);
}







>
>
>
>
>
|







223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
** subsequent push, pull, and sync operations.  However, the "--once"
** command-line option makes the URL a one-time-use URL that is not
** saved.
**
** Use the --private option to sync private branches with the
** remote repository.
**
** Use the "--certgroup NAME" option to specify the name of the
** certificate/key bundle to use for https connections. If this option
** is not specified, a cached value associated with the URL will be
** used if it exists.
**
** See also: cert, clone, push, pull, remote-url
*/
void sync_cmd(void){
  int syncFlags;
  int bPrivate;
  process_sync_args(&syncFlags, &bPrivate);
  client_sync(1,1,0,bPrivate,syncFlags,0);
}