How to make a secure password input field in a command line app? - objective-c

I am writing a command line application for OS X in Swift. I need to prompt for a username and password (not the user's account on the computer and not credentials saved in the Keychain). I can prompt for the username just fine:
func getInput() -> String {
var keyboard = NSFileHandle.fileHandleWithStandardInput()
var inputData = keyboard.availableData
return NSString(data: inputData, encoding:NSUTF8StringEncoding)!.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
}
let username = getInput()
I would like to prompt for the password as well but it prints the password in the console as the user types it. How can I accept input from STDIN without having it echoed back to the console?
Please note that I need the application to be interactive, the user will never be passing the username and password as command line arguments, so argv is not the correct answer.
For example, when doing this in Ruby, you would enter this:
require 'io/console'
puts "Enter your password"
#password = STDIN.noecho(&:gets).chomp
And then it would display on the screen as this image:
No matter how many letters are entered, it only shows that blue box with the dot in it. It doesn't print the password to the screen and it doesn't show ********* for the password either.
Is it possible to do the same thing with Swift or Objective-C in a command line OS X application?

Just for the sake of completeness: getpass() works great for passwords, but unfortunately this function also has the limitation that it can only read up to 128 characters. If you want to prompt for really long passphrase or private keys, use BSD's readpassphrase() instead.
Swift 2.0 example:
var buf = [Int8](count: 8192, repeatedValue: 0)
let passphrase = readpassphrase("Enter passphrase: ", &buf, buf.count, 0)
if let passphraseStr = String.fromCString(passphrase) {
print(passphraseStr)
}
Swift 3.1 and later:
var buf = [CChar](repeating: 0, count: 8192)
if let passphrase = readpassphrase("Enter passphrase: ", &buf, buf.count, 0),
let passphraseStr = String(validatingUTF8: passphrase) {
print(passphraseStr)
}

inputString = String(validatingUTF8: UnsafePointer<CChar>(getpass("Please enter your password: ")))
This is how you could get the input using swift

Use the C function getpass(3). For example:
char *p = getpass("Please enter your password: ");
NSString *password = [NSString stringWithUTF8String:p];
NSLog(#"%#", password);

Related

Keycloak migrating hashed passwords

I'm trying to migrate users from an old Drupal 6 CMS to Keycloak. I'd like to migrate the users with their old passwords and then assigning an "Update Password" required action to their profile.
However migrating the passwords seems problematic as I can only access them in their hashed form.
The passwords are hashed with an MD5 algorithm using no salt.
I've tried migrating them according to this page:
https://lists.jboss.org/pipermail/keycloak-user/2015-December/004212.html
Here's the JSON I'm sending to the Keycloak REST API:
{
"hashedSaltedValue" : "password-hash",
"algorithm" : "restcomm-md5",
"type" : "password",
}
Here's a list of things I've tried
Included a NULL hash value
Included a 0 hashIteration value
Base64 encoded the hash
Converted the hash to binary and then Base64 encoding it
Has anyone ever had any luck getting this feature working?
The following curl command worked for me to migrate a old hashed password. Replace {hashedSaltedValue} with your hashed password and {salt} with you salt.
token="..."
curl 'http://keycloak-http/auth/admin/realms/testrealm/users/f:60f0ff50-2cc5-492d-8222-04ac0a9964e1:217b93e8-2830-4392-83e3-9feceea94575' \
-X PUT \
-H "Authorization: $token" \
-H "Content-Type: application/json" \
--data '{"credentials": [ { "algorithm": "pbkdf2-sha512", "hashedSaltedValue": "{hashedpassword}", "hashIterations": 30000, "type": "password", "salt":"{salt}"}]}'
The parameters hashedSaltedValue etc. are deprecated and keycloak 10 and newer will log a deprecation warning.
There is a new CredentialRepresentation defined where you put JSON into the strings for attributes secretData and credentialData.
I'm so late, but my answer may be useful for someone. I have the same problem, we don't want to notify our users to reset password. We are creating users by Keycloak Admin REST API java client. Our user's password are hashed by MD5 algorithm. By default KK don't support MD5, that's why firstly we import custom MD5 password hash provider. Below piece of code that help us.
#Test
public void createUser() {
UserDTO user = UserDTO.builder()
.email("dake#mail.ru")
.username("dake#mail.ru")
.emailVerified(true)
.build();
String rawPassword = "barcelona";
String md5Password = "dea56e47f1c62c30b83b70eb281a6c39";
UserRepresentation userRepresentation = convertToUserRepresentation(user);
//setUserRepresentationPassword(userRepresentation, rawPassword, true);
setUserRepresentationPassword(userRepresentation, md5Password, false);
createUser(userRepresentation);
}
public static UserRepresentation convertToUserRepresentation(UserDTO userDTO) {
UserRepresentation userRepresentation = new UserRepresentation();
userRepresentation.setId(userDTO.getId());
userRepresentation.setEnabled(true);
userRepresentation.setUsername(userDTO.getUsername());
userRepresentation.setFirstName(userDTO.getFirstName());
userRepresentation.setLastName(userDTO.getLastName());
userRepresentation.setEmail(userDTO.getEmail());
userRepresentation.setEmailVerified(userDTO.isEmailVerified());
userRepresentation.singleAttribute("cityId", userDTO.getCityId() != null ? "" + userDTO.getCityId() : null);
userRepresentation.singleAttribute("phone", userDTO.getPhone());
userRepresentation.singleAttribute("phoneVerified", "" + userDTO.isPhoneVerified());
userRepresentation.singleAttribute("notificationsEnabled", "" + userDTO.isNotificationsEnabled());
return userRepresentation;
}
/**
* #return User uuid
*/
public String createUser(UserRepresentation userRepresentation) {
if (CollectionUtils.isEmpty(userRepresentation.getGroups())) {
userRepresentation.setGroups(Arrays.asList(GROUP_USERS));
}
RealmResource realm = keycloak.realm(realmName);
Response response = realm.users().create(userRepresentation);
if (response.getStatus() < 200 || response.getStatus() > 299) {
String error = "User create error: " + response.readEntity(String.class);
log.error(error);
throw new RuntimeException(error);
}
// Extract the uuid of the user we just created.
String location = response.getMetadata().get("Location").get(0).toString();
String uuid = location.substring(location.lastIndexOf("/") + 1);
log.info("User created: " + uuid);
return uuid;
}
/**
* Set password for user
*
* #param userRepresentation user
* #param password raw(plaintext) password or hashed password(this way is deprecated)
* #param isRawPassword password is plaintext
*/
#SneakyThrows
public static void setUserRepresentationPassword(UserRepresentation userRepresentation, String password, boolean isRawPassword) {
CredentialRepresentation credential = new CredentialRepresentation();
credential.setType(CredentialRepresentation.PASSWORD);
credential.setTemporary(false);
if (isRawPassword) {
credential.setValue(password);
} else {
Field algorithm = credential.getClass().getDeclaredField("algorithm");
algorithm.setAccessible(true);
algorithm.set(credential, "MD5");
Field hashIterations = credential.getClass().getDeclaredField("hashIterations");
hashIterations.setAccessible(true);
hashIterations.set(credential, 0);
Field hashedSaltedValue = credential.getClass().getDeclaredField("hashedSaltedValue");
hashedSaltedValue.setAccessible(true);
hashedSaltedValue.set(credential, password);
}
userRepresentation.setCredentials(Arrays.asList(credential));
}
After that everything is good. I noticed, after I logged in my MD5 password are automatically converted to pbkdf2-sha256.
Keycloak reset-password api is, what you're trying to use?
Using "reset-password" api, I believe it only accepts plain text password, which means, you can't reset-password with already hashed password value.
If you use create user api, then you can add hashed value as password.
I am using Aerobase with Keycloak and try to update password using reset-password api, it's not working with hashed password, it only works with plain text password and then store hashed password instead.
If there's anyone who's successfully reset-password with hashed password, please leave comment here!

user Login web service required using prestashop api

I am working on prestashop web services for my android app, i searched a lot in google, but i did not find proper document/proper explanation. Can any one please guide me how to do user login/authentication using prestashop web services?.
You can make a call to the customer endpoint filtering by the customer's email. The result would have a "passwd" field, which is a hashed password which could either be md5 or bcrypt since Prestashop supports both. You can then hash the customer's password input and compare with the "passwd" field in the response. If the length of the "passwd" field is 32 (md5), you'll need parameter _COOKIE_KEY_ set in /app/config/parameters.php as a salt to generate your hash;
Make the call like this https://yourprestashopurl.com/api/customers?filter[email]=email#email.com&display=full
For md5 (if passwd is 32 characters long):
$hash = md5(_COOKIE_KEY_ . $input_password);
You can then compare $hash with passwd
For bcrypt (if passwd is 60 characters long):
Option 1:
$verify = password_verify($input_password, passwd);
You can accept $input_password when this returns true, otherwise $input_password is invalid
Option 2:
$hash = password_hash($input_password, PASSWORD_BCRYPT);
You can then compare $hash with passwd
Note: password_hash and password_verify are both built-in php functions since PHP 5.5.0
Use the PrestaShop webservices and filter with email and password like below:
http://localhost/api/customers/?filter[email]=test#prestashop.com&filter[password]=19910794b7c0b413e80f58298a8d8300
For those who are still searching for this answer:
<?php
if (isset($_GET["email"]) && isset($_GET["password"]))
{
$email = $_GET["email"];
$password = $_GET["password"];
$COOKIE_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
$jsonurl = "https://XXXXXXXXXXXXXXXXXXXX#example.com/api/customers?filter[email]=".$email."&display=[passwd]&output_format=JSON";
$json = file_get_contents($jsonurl);
$json_a = json_decode($json, true);
$loopone = $json_a['customers'];
$looptwo = $loopone[0];
$loopthree = $looptwo['passwd'];
$ZCpassword = md5($COOKIE_KEY . $password);
if (strcmp($loopthree, $ZCpassword) == 0) {
echo "sucess";
} else {
echo "fail";
}
}
else
{
echo "Error";
}
?>

Objective C : How can we retrieve information stored in Local Items in key chain?

I have saved the username and password for a website in safari, Safari saved this information in Local Items keychain, how can I retrieve stored information using objective C ?
I am trying to retrieve website password stored in Local Items Keychain in OS X version 10.11.4 by safari.
if I access username and password stored in login keychain. then username and password can be retrieved by below code.
OSStatus status;
NSString *account = #"Safari";
const char *cService_name = "PersonalFormsAutoFillDatabase";
UInt32 service_length = strlen(cService_name);
const char *cAccount_name = [account cStringUsingEncoding:NSUTF8StringEncoding];
UInt32 account_length = strlen(cAccount_name);
void *passwordData = nil;
SecKeychainItemRef itemRef = nil;
UInt32 passwordLength = 0;
status = SecKeychainFindGenericPassword(NULL, service_length, cService_name, account_length, cAccount_name, &passwordLength, &passwordData, NULL);
NSString *pw = [[NSString alloc]initWithBytes:passwordData length:passwordLength encoding:NSUTF8StringEncoding];
When i run above code system prompt a popup and ask for permission to allow retrieve the password . if I want to change the default Login Keychain to another keychain then user need to create the reference for new keychain like below code and need to pass reference of new keychain in SecKeychainFindGenericPassword method.
SecKeychainRef keychain ;
OSStatus status1 = SecKeychainOpen("/Users/xxxx/Library/Keychains/mykeychain.keychain", &keychain);
if(status1 != errSecSuccess) {
NSLog(#"Failed to open System keychain %#", SecCopyErrorMessageString(status1, NULL));
}
status1 = SecKeychainUnlock(keychain, 0, NULL, FALSE);
My First question is what will be path for Local Items keychain like “/Users/xxxx/Library/Keychains/mykeychain.keychain” ?
As I don’t have the path then i created a new keychain From File->Add KeyChain and give the name testing.keychain. After that I copied one keychain item form Local Items keychain and Pasted into testing.keychain. and used the above code and changed the path as below.
SecKeychainRef keychain ;
OSStatus status1 = SecKeychainOpen("/Users/xxxx/Library/Keychains/testing.keychain", &keychain);
if(status1 != errSecSuccess) {
NSLog(#"Failed to open System keychain %#", SecCopyErrorMessageString(status1, NULL));
}
status1 = SecKeychainUnlock(keychain, 0, NULL, FALSE);
and passed the reference in find generic password method and also change the service name and account name to "a#gmail.com" and service name "https://accounts.google.com"
status = SecKeychainFindGenericPassword(keychain, service_length, cService_name, account_length, cAccount_name, &passwordLength, &passwordData, NULL);
this return the password data but as i think it is in encrypted mode then it return NULL. How can I decrypt this stored password.
Anyone who can help so i can retrieve the password stored in Local Items keychain.

How to modify admin password on vtiger?

I have to modify the password of an account on a vtiger crm. The problem is that I don't know the location of the database.
Anyone know the path of the database containing the credential of the users?
If your username starts with 'ad' like 'admin'. use the following mysql query
UPDATE vtiger_users SET user_password = '$1$ad000000$mnnPAFfqzJOuoYY7aB.mR0' WHERE user_name='admin';
This query will reset the password for user with admin username. The password will be set to password.
Vtiger use encrypt_password function in Users.php on line 264 to encrypt user password.
modules/Users/Users.php
It use crypt_type and username for encrypt new passwords. so Mysql query only work if your username starts with ad for example 'admin' , 'adam' and etc.
function encrypt_password($user_password, $crypt_type='') {
// encrypt the password.
$salt = substr($this->column_fields["user_name"], 0, 2);
// Fix for: http://trac.vtiger.com/cgi-bin/trac.cgi/ticket/4923
if($crypt_type == '') {
// Try to get the crypt_type which is in database for the user
$crypt_type = $this->get_user_crypt_type();
}
// For more details on salt format look at: http://in.php.net/crypt
if($crypt_type == 'MD5') {
$salt = '$1$' . $salt . '$';
} elseif($crypt_type == 'BLOWFISH') {
$salt = '$2$' . $salt . '$';
} elseif($crypt_type == 'PHP5.3MD5') {
//only change salt for php 5.3 or higher version for backward
//compactibility.
//crypt API is lot stricter in taking the value for salt.
$salt = '$1$' . str_pad($salt, 9, '0');
}
$encrypted_password = crypt($user_password, $salt);
return $encrypted_password;
}
You can use the following tools on Github. it can change all users password without login into crm and phpmyadmin and update vtiger user privileges file.
https://github.com/spadana2004/Vtiger-CRM-Reset-Password-Tools
Go to My preferences(right top of the browser). There you can change the password of the user.
In database you can't change bcoz there it will be converted to MD5. Then also for your kind information in database check the table vtiger_users for user detail.
update vtiger_users set user_password = 'adpexzg3FUZAk', crypt_type = '' where id = '1';
Login: admin
Password:admin
To make this really easy for admins I created a simple gist that will generate the sql query you need to run to reset a password with any username. Just put in the username and temp password, then run the script and use the SQL it provides. After that just login with that username and password. It is tested with and working on VTiger 7.2.
https://gist.github.com/mav2287/59d5587c7efabdbb105b739c4bc27cb5
<?php
// Put in your username as found in the "vtiger_users" table under the "username" column
$user_name = "";
// Set your TEMPORARY password. You NEED to reset your password after using this to reset it.
$user_password = "password";
// return the approiate stamtent
echo "Run the following SQL query to reset your password: \n";
echo "\"UPDATE vtiger_users SET user_password='".crypt($user_password, substr($user_name, 0, 2))."',crypt_type=''WHERE user_name='".$user_name."'\"";

Retrieve username and password from text files and collect them in a log in variable(params)

I have got a function that stores the username and password in each separate text files (Titanium.Filesystem.applicationDataDirectory, "userName.txt") and (Titanium.Filesystem.applicationDataDirectory, "passWord.txt") after the login has been confirmed valid by the webserver(php).
Now I need a function that retrieve the values(text content) from userName.txt and passWord.txt and collect these values in a var params that post them to the php-server on an event:
var params = {
username: username.value,
password: Ti.Utils.md5HexDigest(password.value)
};
Why don't you use the Ti.App.Properties? It is designed for storing data just like this.
Ti.App.Properties.setString('username', username.value);
username.value = Ti.App.Properties.getString('username');
http://docs.appcelerator.com/titanium/2.0/index.html#!/api/Titanium.App.Properties
If you must use files (which I do not recommend):
var file = Ti.Filesystem.getFile(Ti.Filesystem.applicationDataDirectory, 'username.txt');
file.write(username.value);
username.value = file.read();