diff --git a/packages/dart/noports_core/lib/src/srvd/srvd_params.dart b/packages/dart/noports_core/lib/src/srvd/srvd_params.dart index e1cd4d42f..1a8aa5bf0 100644 --- a/packages/dart/noports_core/lib/src/srvd/srvd_params.dart +++ b/packages/dart/noports_core/lib/src/srvd/srvd_params.dart @@ -8,6 +8,7 @@ class SrvdParams { final String atSign; final String homeDirectory; final String atKeysFilePath; + final String passPhrase; final String managerAtsign; final String ipAddress; final bool verbose; @@ -30,6 +31,7 @@ class SrvdParams { required this.atSign, required this.homeDirectory, required this.atKeysFilePath, + required this.passPhrase, required this.managerAtsign, required this.ipAddress, required this.verbose, @@ -58,6 +60,7 @@ class SrvdParams { homeDirectory: homeDirectory, atKeysFilePath: r['key-file'] ?? getDefaultAtKeysFilePath(homeDirectory, atSign), + passPhrase: r['pass-phrase'], managerAtsign: r['manager'], ipAddress: r['ip'], verbose: r['verbose'], @@ -87,6 +90,16 @@ class SrvdParams { 'atSign\'s atKeys file if not in ~/.atsign/keys/' ' Alias: --keyFile', ); + parser.addOption( + 'pass-phrase', + aliases: const ['passPhrase'], + abbr: 'P', + help: + 'Pass Phrase to encrypt/decrypt the password protected atKeys file', + mandatory: false, + defaultsTo: '', + hide: true + ); parser.addOption( 'atsign', abbr: 'a', diff --git a/packages/dart/noports_core/lib/src/sshnp/models/sshnp_arg.dart b/packages/dart/noports_core/lib/src/sshnp/models/sshnp_arg.dart index 3069875bb..48bf5da42 100644 --- a/packages/dart/noports_core/lib/src/sshnp/models/sshnp_arg.dart +++ b/packages/dart/noports_core/lib/src/sshnp/models/sshnp_arg.dart @@ -93,6 +93,7 @@ class SshnpArg { profileNameArg, helpArg, keyFileArg, + passPhraseArg, fromArg, toArg, deviceArg, @@ -200,6 +201,14 @@ class SshnpArg { help: 'Sending atSign\'s atKeys file if not in ~/.atsign/keys/', parseWhen: ParseWhen.commandLine, ); + static const passPhraseArg = SshnpArg( + name: 'pass-phrase', + aliases: ['passPhrase'], + abbr: 'P', + help: 'Pass Phrase to encrypt/decrypt the password protected atKeys file', + mandatory: false, + defaultsTo: '', + ); static const fromArg = SshnpArg( name: 'from', abbr: 'f', diff --git a/packages/dart/noports_core/lib/src/sshnp/models/sshnp_params.dart b/packages/dart/noports_core/lib/src/sshnp/models/sshnp_params.dart index 342f0d9ad..a75e47cdc 100644 --- a/packages/dart/noports_core/lib/src/sshnp/models/sshnp_params.dart +++ b/packages/dart/noports_core/lib/src/sshnp/models/sshnp_params.dart @@ -31,6 +31,8 @@ abstract interface class ClientParams { String? get atKeysFilePath; + String? get passPhrase; + /// An encryption keypair which should only ever reside in memory. /// The public key is provided in requests to the daemon, and is /// used by daemons to encrypt symmetric encryption keys intended for @@ -83,6 +85,9 @@ abstract class ClientParamsBase implements ClientParams { @override final String? atKeysFilePath; + @override + final String? passPhrase; + @override int localPort; @@ -111,6 +116,7 @@ abstract class ClientParamsBase implements ClientParams { this.device = DefaultSshnpArgs.device, this.verbose = DefaultArgs.verbose, this.atKeysFilePath, + this.passPhrase, this.rootDomain = DefaultArgs.rootDomain, this.authenticateClientToRvd = DefaultArgs.authenticateClientToRvd, this.authenticateDeviceToRvd = DefaultArgs.authenticateDeviceToRvd, @@ -180,6 +186,7 @@ class NptParams extends ClientParamsBase super.localPort = DefaultSshnpArgs.localPort, super.verbose = DefaultArgs.verbose, super.atKeysFilePath, + super.passPhrase, super.rootDomain = DefaultArgs.rootDomain, super.authenticateClientToRvd = DefaultArgs.authenticateClientToRvd, super.authenticateDeviceToRvd = DefaultArgs.authenticateDeviceToRvd, @@ -258,6 +265,7 @@ class SshnpParams extends ClientParamsBase this.remoteUsername, this.tunnelUsername, super.atKeysFilePath, + super.passPhrase, super.rootDomain = DefaultArgs.rootDomain, this.listDevices = DefaultSshnpArgs.listDevices, this.remoteSshdPort = DefaultArgs.remoteSshdPort, @@ -296,6 +304,7 @@ class SshnpParams extends ClientParamsBase device: params2.device ?? params1.device, localPort: params2.localPort ?? params1.localPort, atKeysFilePath: params2.atKeysFilePath ?? params1.atKeysFilePath, + passPhrase: params2.passPhrase ?? params1.passPhrase, identityFile: params2.identityFile ?? params1.identityFile, identityPassphrase: params2.identityPassphrase ?? params1.identityPassphrase, @@ -364,6 +373,7 @@ class SshnpParams extends ClientParamsBase remoteUsername: partial.remoteUsername, tunnelUsername: partial.tunnelUsername, atKeysFilePath: partial.atKeysFilePath, + passPhrase: partial.passPhrase, rootDomain: partial.rootDomain ?? DefaultArgs.rootDomain, listDevices: partial.listDevices ?? DefaultSshnpArgs.listDevices, remoteSshdPort: partial.remoteSshdPort ?? DefaultArgs.remoteSshdPort, @@ -417,6 +427,7 @@ class SshnpParams extends ClientParamsBase SshnpArg.deviceArg.name: device, SshnpArg.localPortArg.name: localPort, SshnpArg.keyFileArg.name: atKeysFilePath, + SshnpArg.passPhraseArg.name: passPhrase, SshnpArg.identityFileArg.name: identityFile, SshnpArg.identityPassphraseArg.name: identityPassphrase, SshnpArg.sendSshPublicKeyArg.name: sendSshPublicKey, @@ -455,6 +466,7 @@ class SshnpPartialParams { final String? device; final int? localPort; final String? atKeysFilePath; + final String? passPhrase; final String? identityFile; final String? identityPassphrase; final bool? sendSshPublicKey; @@ -485,6 +497,7 @@ class SshnpPartialParams { this.device, this.localPort, this.atKeysFilePath, + this.passPhrase, this.identityFile, this.identityPassphrase, this.sendSshPublicKey, @@ -525,6 +538,7 @@ class SshnpPartialParams { device: params2.device ?? params1.device, localPort: params2.localPort ?? params1.localPort, atKeysFilePath: params2.atKeysFilePath ?? params1.atKeysFilePath, + passPhrase: params2.passPhrase ?? params1.passPhrase, identityFile: params2.identityFile ?? params1.identityFile, identityPassphrase: params2.identityPassphrase ?? params1.identityPassphrase, @@ -585,6 +599,7 @@ class SshnpPartialParams { device: args[SshnpArg.deviceArg.name], localPort: args[SshnpArg.localPortArg.name], atKeysFilePath: args[SshnpArg.keyFileArg.name], + passPhrase: args[SshnpArg.passPhraseArg.name], identityFile: args[SshnpArg.identityFileArg.name], identityPassphrase: args[SshnpArg.identityPassphraseArg.name], sendSshPublicKey: args[SshnpArg.sendSshPublicKeyArg.name], diff --git a/packages/dart/noports_core/lib/src/sshnpd/sshnpd_params.dart b/packages/dart/noports_core/lib/src/sshnpd/sshnpd_params.dart index 7b67dd083..5c8ca87b2 100644 --- a/packages/dart/noports_core/lib/src/sshnpd/sshnpd_params.dart +++ b/packages/dart/noports_core/lib/src/sshnpd/sshnpd_params.dart @@ -5,6 +5,7 @@ import 'package:at_cli_commons/at_cli_commons.dart'; import 'package:noports_core/src/common/default_args.dart'; import 'package:noports_core/src/common/types.dart'; import 'package:noports_core/src/common/validation_utils.dart'; +import 'package:at_utils/at_utils.dart'; class SshnpdParams { final String device; @@ -13,6 +14,7 @@ class SshnpdParams { final List managerAtsigns; final String? policyManagerAtsign; final String atKeysFilePath; + final String passPhrase; final String deviceAtsign; final bool verbose; final bool makeDeviceInfoVisible; @@ -38,6 +40,7 @@ class SshnpdParams { required this.managerAtsigns, required this.policyManagerAtsign, required this.atKeysFilePath, + required this.passPhrase, required this.deviceAtsign, required this.verbose, required this.makeDeviceInfoVisible, @@ -62,7 +65,7 @@ class SshnpdParams { // Arg check ArgResults r = parser.parse(args); - String deviceAtsign = r['atsign']; + String deviceAtsign = AtUtils.fixAtSign(r['atsign']); if (!r.wasParsed('managers') && !r.wasParsed('policy-manager')) { throw ArgumentError( @@ -123,6 +126,7 @@ class SshnpdParams { atKeysFilePath: r['key-file'] ?? getDefaultAtKeysFilePath(homeDirectory, deviceAtsign), + passPhrase: r['pass-phrase'], deviceAtsign: deviceAtsign, verbose: r['verbose'], makeDeviceInfoVisible: makeDeviceInfoVisible, @@ -164,6 +168,16 @@ class SshnpdParams { ' Alias: --keyFile', ); + parser.addOption( + 'pass-phrase', + aliases: ['passPhrase'], + abbr: 'P', + mandatory: false, + defaultsTo: '', + help: 'Pass Phrase to encrypt/decrypt the password protected atKeys file', + hide: true + ); + parser.addOption( 'atsign', abbr: 'a', diff --git a/packages/dart/sshnoports/bin/npt.dart b/packages/dart/sshnoports/bin/npt.dart index dc7e12b5e..41c688120 100644 --- a/packages/dart/sshnoports/bin/npt.dart +++ b/packages/dart/sshnoports/bin/npt.dart @@ -265,6 +265,11 @@ void main(List args) async { negatable: true, ); + parser.addOption('passPhrase', + abbr: 'P', + mandatory: false, + help: 'The pass phrase to access the password protected atKeys file'); + parser.addOption( 'relay-auth-mode', aliases: ['ram'], @@ -376,7 +381,8 @@ void main(List args) async { homeDir: getHomeDirectory(), storageDir: storageDir?.path, verbose: parsedArgs['verbose'], - syncDisabled: true); + syncDisabled: true, + passPhrase: parsedArgs['passPhrase']); await cliBase.init(); diff --git a/packages/dart/sshnoports/bin/srvd.dart b/packages/dart/sshnoports/bin/srvd.dart index 8849c602a..d7993d6e1 100644 --- a/packages/dart/sshnoports/bin/srvd.dart +++ b/packages/dart/sshnoports/bin/srvd.dart @@ -103,6 +103,7 @@ void main(List args) async { storagePath: storageDir.path, atsign: p.atSign, atKeysFilePath: p.atKeysFilePath, + passPhrase: p.passPhrase, namespace: Srvd.namespace, rootDomain: p.rootDomain, atServiceFactory: ServiceFactoryWithNoOpSyncService(), diff --git a/packages/dart/sshnoports/bin/sshnp.dart b/packages/dart/sshnoports/bin/sshnp.dart index af9c0a80f..5d195affb 100644 --- a/packages/dart/sshnoports/bin/sshnp.dart +++ b/packages/dart/sshnoports/bin/sshnp.dart @@ -150,6 +150,7 @@ void main(List args) async { atsign: params.clientAtSign, atKeysFilePath: params.atKeysFilePath ?? getDefaultAtKeysFilePath(homeDirectory, params.clientAtSign), + passPhrase: params.passPhrase, rootDomain: params.rootDomain, storagePath: storageDir!.path, namespace: DefaultArgs.namespace, diff --git a/packages/dart/sshnoports/bin/sshnpd.dart b/packages/dart/sshnoports/bin/sshnpd.dart index a8f495407..5501a9235 100644 --- a/packages/dart/sshnoports/bin/sshnpd.dart +++ b/packages/dart/sshnoports/bin/sshnpd.dart @@ -27,6 +27,7 @@ void main(List args) async { atClientGenerator: (SshnpdParams p) => createAtClientCli( atsign: p.deviceAtsign, atKeysFilePath: p.atKeysFilePath, + passPhrase: p.passPhrase, rootDomain: p.rootDomain, storagePath: p.storagePath, namespace: DefaultArgs.namespace, diff --git a/packages/dart/sshnoports/lib/src/create_at_client_cli.dart b/packages/dart/sshnoports/lib/src/create_at_client_cli.dart index 3d481435e..d880a7b56 100644 --- a/packages/dart/sshnoports/lib/src/create_at_client_cli.dart +++ b/packages/dart/sshnoports/lib/src/create_at_client_cli.dart @@ -6,6 +6,7 @@ import 'package:path/path.dart' as path; Future createAtClientCli({ required String atsign, required String atKeysFilePath, + String? passPhrase = '', required AtServiceFactory atServiceFactory, required String storagePath, required String namespace, @@ -26,6 +27,7 @@ Future createAtClientCli({ ..commitLogPath = path.normalize('$storagePath/commitLog') ..fetchOfflineNotifications = false ..atKeysFilePath = atKeysFilePath + ..passPhrase = passPhrase ..rootDomain = domain ..rootPort = port;