Subversion Repositories zfs_utils

Rev

Rev 37 | Rev 39 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 37 Rev 38
Line 248... Line 248...
248
 
248
 
249
    return $yaml;
249
    return $yaml;
250
}
250
}
251
 
251
 
252
 
252
 
253
 
-
 
-
 
253
# Mount a GELI-encrypted ZFS pool.
-
 
254
# $geliConfig - hashref containing configuration for geli
-
 
255
# Returns the pool name on success, empty string on error.
254
sub mountGeli {
256
sub mountGeli {
255
   my $geliConfig = shift;
257
   my $geliConfig = shift;
-
 
258
 
-
 
259
   # Can't continue at all if no pool name
256
   unless ( $geliConfig->{'localKey'} ) {
260
   unless ( $geliConfig->{'poolname'} ) {
257
      logMsg "Could not find local key in configuration file\n";
261
      logMsg "Could not find pool name in configuration file\n";
258
      return '';
262
      return '';
259
   }
263
   }
-
 
264
 
260
   # find the keyfile disk and mount it
265
   # find the keyfile disk and mount it
261
   my $path = mountDriveByLabel( $geliConfig->{'keydiskname'} );
266
   $geliConfig->{secureKey}->{path} = mountDriveByLabel( $geliConfig->{secureKey}->{label} );
262
   unless ( $path ne '' and -e "$path/" . $geliConfig->{'keyfile'} ) {
267
   unless ( $geliConfig->{secureKey}->{path} ne '' ) {
263
      logMsg "Could not find or mount keyfile disk with label: " . $geliConfig->{'keydiskname'} . "\n";
268
      logMsg "Could not find or mount keyfile disk with label: " . $geliConfig->{secureKey}->{label};
264
      return '';
269
      return '';
265
   }
270
   }
266
   # create the combined geli keyfile in target location
271
   # create the combined geli keyfile in target location
267
   unless ( makeGeliKey( "$path/" . $geliConfig->{'keyfile'}, $geliConfig->{'localKey'}, $geliConfig->{'target'} ) ) {
272
   unless ( makeGeliKey( $geliConfig ) ) {
268
         logMsg "Could not create geli keyfile\n";
273
         logMsg "Could not create geli keyfile\n";
269
         return '';
274
         return '';
270
      }
275
      }
271
   # decrypt and mount the geli disks and zfs pool
276
   # decrypt and mount the geli disks and zfs pool
-
 
277
   die;
272
   my $poolname = decryptAndMountGeli( $geliConfig );
278
   my $poolname = decryptAndMountGeli( $geliConfig );
273
   return $poolname;
279
   return $poolname;
274
                                                
280
                                                
275
}
281
}
276
 
282
 
Line 301... Line 307...
301
## Decrypt each GELI disk from $geliConfig->{'diskList'} using the keyfile,
307
## Decrypt each GELI disk from $geliConfig->{'diskList'} using the keyfile,
302
## then import and mount the ZFS pool specified in $geliConfig->{'poolname'}.
308
## then import and mount the ZFS pool specified in $geliConfig->{'poolname'}.
303
##
309
##
304
## Returns the pool name on success, empty on error.
310
## Returns the pool name on success, empty on error.
305
sub decryptAndMountGeli {
311
sub decryptAndMountGeli {
306
   my ($geliConfig) = @_;
312
   my ($geliConfig) = shift;
307
   
313
   
308
   # Can't continue at all if no pool name
-
 
309
   die "No pool name specified in config\n" unless $geliConfig->{'poolname'};
-
 
310
   # if no list of disks provided, try to find them
314
   # if no list of disks provided, try to find them
311
   $geliConfig->{'diskList'} //= findGeliDisks();
315
   $geliConfig->{'diskList'} //= findGeliDisks();
312
   
316
   
313
   my $diskList = $geliConfig->{'diskList'};
317
   my $diskList = $geliConfig->{'diskList'};
314
   my $poolname = $geliConfig->{'poolname'};
318
   my $poolname = $geliConfig->{'poolname'};
Line 381... Line 385...
381
##   $localKeyHexOrPath - hex string (64 hex chars) or path to file containing hex
385
##   $localKeyHexOrPath - hex string (64 hex chars) or path to file containing hex
382
##   $target - path to write the resulting 32-byte binary key
386
##   $target - path to write the resulting 32-byte binary key
383
##
387
##
384
## Returns true on success, dies on fatal error.
388
## Returns true on success, dies on fatal error.
385
sub makeGeliKey {
389
sub makeGeliKey {
386
   my ($remote_keyfile, $localKeyHexOrPath, $target) = @_;
390
   my ( $geliConfig ) = @_;
387
 
391
 
388
   die "remote keyfile not provided" unless defined $remote_keyfile;
392
   $geliConfig->{secureKey}->{keyfile} //= '';
389
   die "local key not provided" unless defined $localKeyHexOrPath;
393
   $geliConfig->{localKey} //= '';
390
   die "target not provided" unless defined $target;
394
   $geliConfig->{target} //= '';
391
 
395
 
-
 
396
   if ( $geliConfig->{target} && -f $geliConfig->{target} ) {
-
 
397
      logMsg "GELI target keyfile $geliConfig->{target} already exists. Not overwriting.\n";
-
 
398
      return 1;
-
 
399
   }
-
 
400
 
-
 
401
   my $remote_keyfile = "$geliConfig->{secureKey}->{path}/$geliConfig->{secureKey}->{keyfile}";
-
 
402
   my $localKeyHexOrPath = $geliConfig->{localKey};
-
 
403
   my $target = $geliConfig->{target};
-
 
404
   
-
 
405
   if ( $geliConfig->{secureKey}->{keyfile} && $geliConfig->{localKey} ) {
-
 
406
      # we have what we need to proceed
-
 
407
 
-
 
408
      if ( -f $remote_keyfile ) {
-
 
409
         logMsg "Creating GELI keyfile at $geliConfig->{target} using remote keyfile " . $geliConfig->{secureKey}->{keyfile} . " and local key\n";
-
 
410
      } else {
392
   die "Remote keyfile $remote_keyfile does not exist\n" unless -e $remote_keyfile;
411
         die "Remote keyfile " . $geliConfig->{secureKey}->{keyfile} . " does not exist\n";
-
 
412
      }
-
 
413
   }
393
 
414
 
394
   # Read remote binary key
415
   # Read remote binary key
395
   open my $rh, '<:raw', $remote_keyfile or die "Unable to open $remote_keyfile: $!\n";
416
   open my $rh, '<:raw', $remote_keyfile or die "Unable to open $remote_keyfile: $!\n";
396
   my $rbuf;
417
   my $rbuf;
397
   my $read = read($rh, $rbuf, 32);
418
   my $read = read($rh, $rbuf, 32);