Index: ScryptPWGen.m ================================================================== --- ScryptPWGen.m +++ ScryptPWGen.m @@ -58,11 +58,11 @@ }; OFOptionsParser *optionsParser = [OFOptionsParser parserWithOptions: options]; of_unichar_t option; char *passphrase; - OFString *site, *prompt; + OFString *prompt; while ((option = [optionsParser nextOption]) != '\0') { switch (option) { case 'h': showHelp(of_stdout, true); @@ -105,14 +105,10 @@ showHelp(of_stderr, false); [OFApplication terminateWithStatus: 1]; } - site = [[optionsParser remainingArguments] firstObject]; - prompt = [OFString stringWithFormat: @"Passphrase for site \"%@\": ", - site]; - id generator = (_legacy ? [LegacyPasswordGenerator generator] : [NewPasswordGenerator generator]); generator.site = [[optionsParser remainingArguments] firstObject]; @@ -134,13 +130,44 @@ [OFApplication terminateWithStatus: 1]; } } + + prompt = [OFString stringWithFormat: @"Passphrase for site \"%@\": ", + generator.site]; passphrase = getpass( [prompt cStringWithEncoding: [OFSystemInfo native8BitEncoding]]); @try { + if (_repeat) { + char *passphraseCopy = of_strdup(passphrase); + + if (passphraseCopy == NULL) + @throw [OFOutOfMemoryException exception]; + + @try { + of_string_encoding_t encoding = + [OFSystemInfo native8BitEncoding]; + + prompt = [OFString stringWithFormat: + @"Repeat passphrase for site \"%@\": ", + generator.site]; + passphrase = getpass( + [prompt cStringWithEncoding: encoding]); + + if (strcmp(passphrase, passphraseCopy) != 0) { + [of_stderr writeString: + @"Passphrases do not match!\n"]; + [OFApplication terminateWithStatus: 1]; + } + } @finally { + of_explicit_memset(passphraseCopy, 0, + strlen(passphraseCopy)); + free(passphraseCopy); + } + } + generator.passphrase = passphrase; [generator derivePassword]; @try { [of_stdout writeBuffer: generator.output