Writing a custom script
The following describes how to write a custom system script used to create a resource profile. Once the system script is written, you may add or update a resource profile that contains the script and then add a system of that type.
Note: Scripts must be written in JavaScript, extensive JavaScript knowledge is not required.
The script must implement two functions as follows:
getAttributes()
The script must implement the getAttributes() function. It indicates the functionality your script provides and additional configuration information.
Example:
function getAttributes() {
var attributes = {
CanChangeOwnPassword: false,
AdministrativeAccountSupported: false
};
return attributes;
}
The remaining functions you write consist of send and expect verbs that are invoked with the sshSend() and sshExpect() functions.
verifyPassword()
The verifyPassword() function is required and allows Privileged Access Service to determine if a username/password combination is valid. When the verifyPassword() function is invoked, Privileged Access Service logs into the system and nothing more may be needed to validate that the user name and password combination is valid.
Example:
Note: The following is an implementation of verifyPassword() that ensures a command prompt outputs by the target system:
function verifyPassword(verifyPasswordInfo) {
// Expect a prompt.
var result = sshExpect(["Prompt> $"]);
if (result.MatchIndex < 0) {
return ErrorInvalidUserPassword;
}
// Password is OK.
return Success;
}
sshExpect()
The following are true for sshExpect():
- The sshExpect() function is called and commands to wait until the target system outputs the string "Prompt> ".
- If the target system does not output the expected string, your script returns an error code.
- The argument to the sshExpect() function is a list of regular expressions to expect.
- If the result.MatchIndex returned is less than zero, the expected string was not output by the target system.
Putting it all together
Finally, put together the complete script as follows:
function getAttributes() {
var attributes = {
CanChangeOwnPassword: false,
AdministrativeAccountSupported: false
};
return attributes;
}
function verifyPassword(verifyPasswordInfo) {
// Expect a prompt.
var result = sshExpect(["Prompt> $"]);
if (result.MatchIndex < 0) {
return ErrorInvalidUserPassword;
}
// Password is OK.
return Success;
}
You can now create a new resource profile with this script and start adding systems of this type. This script allows you to create systems and accounts with vaulted passwords, control who has access to those accounts, initiate workflow for requesting temporary access to a system, and audit use of an account.

A standalone SSH test utility allows you to test and debug your script before using it to create a resource profile. The test utility runs on Windows systems and is a command-line tool suitable for integration into a test harness. To download the SSH test utility, from the Admin Portal, navigate to Download > Tools > Centrify SSH Test Kit.
Test loading of your script
Take the script you created and add it to a file entitled "device-script.js". You can now add a number of arguments to SSH test utility, many of which are optional. You must, however, specify the --script parameter, and one of the "operation" parameters such as --load.
Example:
> SshTest --script device-script.js --load
TEST(Info): Load script result = Success
>
The --load parameter asks SSH test utility to load the JavaScript, test for syntax errors, invoke the getAttributes() function and verify that the attributes are legal.
Example:
Modify the script to include a syntax error by removing the colon after CanChangeOwnPassword in the getAttributes() function as follows:
function getAttributes() {
var attributes = {
CanChangeOwnPassword false,
AdministrativeAccountSupported: false
};
return attributes;
}
function verifyPassword(verifyPasswordInfo) {
// Expect a prompt.
var result = sshExpect(["Prompt> $"]);
if (result.MatchIndex < 0) {
return ErrorInvalidUserPassword;
}
// Password is OK.
return Success;
}
Now, SSH test utility reports the error:
> SshTest --script device-script.js --load
TEST(Error): no viable alternative at input 'CanChangeOwnPassword' at line 4:9
>
Similarly, put the colon back in and change the attribute to an invalid one:
function getAttributes() {
var attributes = {
ThisIsNotAValidAttribute: false,
AdministrativeAccountSupported: false
};
return attributes;
}
function verifyPassword(verifyPasswordInfo) {
// Expect a prompt.
var result = sshExpect(["Prompt> $"]);
if (result.MatchIndex < 0) {
return ErrorInvalidUserPassword;
}
// Password is OK.
return Success;
}
SSH test utility reports the error as follows:
> SshTest --script device-script.js --load
TEST(Error): Attribute 'ThisIsNotAValidAttribute' is not valid
>
Testing Password Verification
To test your verifyPassword() function, use the --verify parameter and supply additional arguments.
Example:
> SshTest --script device-script.js --verify --host hatter-rh.richl.devp --user local2 --password local2pass
TEST(Info): Verify password result = Success
>
Using script parameter shortcuts
Many SSH test utility parameters have shortcuts for the parameter names.
Example, instead of:
> SshTest --script device-script.js --verify --host hatter-rh.richl.devp --user local2 --password local2pass
use:
> SshTest -s device-script.js -v -h hatter-rh.richl.devp -u local2 -p local2pass
Using script logging
You can get additional logging output to help diagnose issues with your scripts. For example, to see details of the "send/expect" interaction with the target system, use the --show-detailed-log parameter:
Example:
> SshTest -s device-script.js -v -h hatter-rh.richl.devp -u local2 -p local2pass --show-detailed-log
INTE(Verbose): getAttributes() completed using 3 statements (start=4, end=7)
INTE(Verbose): sshExpect: expect=(Count=1, Values=('Prompt> $'))
INTE(Verbose): Matching: 'Prompt> $' to '^[]0;local2@hatter-rh:~^GPrompt> '
INTE(Verbose): Matched: 'Prompt> $' to 'Prompt> '
INTE(Verbose): sshExpect: found 'Prompt> $' with match index 0
INTE(Verbose): verifyPassword() completed using 4 statements (start=7, end=11)
TEST(Info): Verify password result = Success
>
- Messages with an INTE prefix indicate messages generated internally by the script processor.
- Messages with a TEST prefix come directly from the SSH test utility.
Additional logging
You can add additional logging into your script to help diagnose problems. For example change your script as follows:
function getAttributes() {
var attributes = {
CanChangeOwnPassword false,
AdministrativeAccountSupported: false
};
return attributes;
}
function verifyPassword(verifyPasswordInfo) {
verbose("Starting execution of verifyPassword");
verbose("userName = " + verifyPasswordInfo.userName);
verbose("userPassword = " + verifyPasswordInfo.userPassword);
// Expect a prompt.
var result = sshExpect(["Prompt> $"]);
if (result.MatchIndex < 0) {
return ErrorInvalidUserPassword;
}
verbose("Everything went OK");
// Password is OK.
return Success;
}
Messages that you generate from your script have a JINT prefix to indicate they came from the JavaScript interpreter:
> SshTest -s device-script.js -v -h hatter-rh.richl.devp -u local2 -p local2pass --show-detailed-log
JINT(Verbose): Starting execution of verifyPassword
JINT(Verbose): userName = local2
JINT(Verbose): userPassword = <hidden>
JINT(Verbose): Everything went OK
TEST(Info): Verify password result = Success
>
View password parameter
For security, the password is scrubbed from the output of the SSH test utility. To view the password passed to your verifyPassword() method, use the --show-passwords option.
> SshTest -s device-script.js -v -h hatter-rh.richl.devp -u local2 -p local2pass --show-detailed-log --show-passwords
JINT(Verbose): Starting execution of verifyPassword
JINT(Verbose): userName = local2
JINT(Verbose): userPassword = local2pass
JINT(Verbose): Everything went OK
TEST(Info): Verify password result = Success
>
Note: If you are verifying a username and password and see that your verifyPassword() function is not called, there may be a connection issue.
In the following example, where the target system is not running, you might see:
> SshTest -s device-script.js -v -h hatter-rh.richl.devp -u local2 -p local2pass
TEST(Error): Connection failed: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 172.27.14.237:22
Connection details parameter
In the unlikely event there is an error in establishing the connection, you can use the --show-connection-log parameter to see all the details of connection establishment.

With Privileged Access Service managed accounts, Privileged Access Service will change the password of the account to a cryptic password. Depending on how you configure Privileged Access Service, you can SSH into a system without having to know the password for the account. Sophisticated access control configuration determines who has this access. Additionally, Privileged Access Service can periodically rotate the password to provide added security. These features accrue to your custom device by setting your CanChangeOwnPassword attribute to true and supplying the changePassword() method.
The following script builds on the script you created above:
info("+++ dev2.js loading");
// Script supporting password verification and changing own password.
var PROMPT = "\\$ $";
var PASSWORD_PROMPT = "(?i)password:";
function getAttributes() {
verbose("getAttributes - starting");
// Capabilities of the system and script.
var attributes = {
CanChangeOwnPassword: true,
AdministrativeAccountSupported: false,
ProxyAccountSupported: false,
DefaultSshPort: 22,
ExpectTimeout: 10000
};
info("getAttributes - returning " + stringify(attributes));
return attributes;
}
function verifyPassword(verifyPasswordInfo) {
verbose("verifyPassword: userName = " + stringify(verifyPasswordInfo));
// Expect a shell prompt.
var result = sshExpect([PROMPT]);
if (result.MatchIndex < 0) {
return ErrorInvalidUserPassword;
}
// Password is OK.
return Success;
}
function changePassword(changePasswordInfo) {
verbose("changePassword: changePasswordInfo = " + stringify(changePasswordInfo));
// Expect a shell prompt.
var result = sshExpect([PROMPT]);
if (result.MatchIndex < 0) {
return ErrorUnexpectedResult;
}
//////////////////
// Send 'passwd' command.
verbose("Sending 'passwd' command...");
sshSend("passwd\r");
// Expect password prompt.
result = sshExpect([PASSWORD_PROMPT]);
if (result.MatchIndex < 0) {
return ErrorUnexpectedResult;
}
////////////////
// Send the old password.
verbose("Sending old password...");
sshSend(changePasswordInfo.userPassword + "\r");
// Expect a new password prompt.
result = sshExpect([PASSWORD_PROMPT, PROMPT]);
if (result.MatchIndex < 0) {
return ErrorUnexpectedResult;
}
////////////////
// Send the new password.
verbose("Sending new password...");
sshSend(changePasswordInfo.newPassword + "\r");
// Expect a confirm password prompt.
result = sshExpect([PASSWORD_PROMPT, PROMPT]);
if (result.MatchIndex < 0) {
return ErrorUnexpectedResult;
}
////////////////
// Send new password confirmation.
verbose("Sending new password again...");
sshSend(changePasswordInfo.newPassword + "\r");
// Expect a shell prompt.
result = sshExpect([PROMPT]);
if (result.MatchIndex < 0) {
return ErrorUncertain;
}
////////////////
// Send command to get last status code.
verbose("Sending command to get status code...");
sshSend("echo $?\r");
// Expect command prompt.
result = sshExpect([PROMPT]);
verbose("status result = " + stringify(result));
if (result.MatchIndex < 0) {
return ErrorUncertain;
}
// Do tricky stuff to get the status code output.
var lines = result.Before.toString().replace(/\r/gm, "").replace(/^\n+/, "").replace(/\n+$/, "").split("\n");
verbose("status lines = " + stringify(lines));
var status = lines[1];
if (status != "0") {
return ErrorFailure;
}
return Success;
}
Script features
Script | Description |
info("getAttributes - returning " + stringify(attributes)); |
This illustrates the stringify() function you can use to convert a JavaScript object into a string, which is useful when writing diagnostic messages. |
result = sshExpect([PASSWORD_PROMPT, PROMPT]); |
This shows how you can specify multiple regular expressions that you might expect. The sshExpect() MatchIndex tells you the patterns that were matched or -1 if none of the expected patterns was matched. |
var lines = result.Before.toString().replace(/\r/gm, "").replace(/^\n+/, "").replace(/\n+$/, "").split("\n"); |
This code snippet shows two concepts:
The first is that the result of calling sshExpect returns an object with four pieces of information: -MatchIndex: this is the index of matched expression. -Before: this is the output text before the match was found. -Match: this is the actual part of the output that matched. -After: this is output text after the match.
The second concept is the use of some of the standard JavaScript functions that manipulate strings (for example: replacing parts of strings and splitting them). In this case, the sequence takes the output before the match, removes "\r" (carriage returns), removes duplicate newlines, and then splits the string into an array of strings - one for each line of output. |
ErrorUncertain status
In the case of the following line:
return ErrorUncertain;
This line conveys there are several error status codes that your script can return when the function is unable to successfully do its job. In this case, ErrorUncertain indicates that the change password operation did not work and there is no confirmation of a password change. This status result tells Privileged Access Service that it needs to determine whether the password change took affect by checking both the old password and the new password.

If the password for an account stored in Privileged Access Service gets out of sync with the actual password, Privileged Access Service permits password reconciliation. For example, if Privileged Access Service is managing an account and a user logs into the system and manually changes the password for the account, the passwords will be out of sync. To support this reconciliation, a privileged "administrative" account for the system is configured and this account is used to forcefully reset the password for the account that is out of sync. For your script to support this functionality, set the AdministrativeAccountSupported attribute to true and supply a setPassword() function.
The following example illustrates this:
info("+++ dev3.js loading");
// Script supporting password verification, and changing own password.
// Reconciliation of out-of-sync passwords supported.
// Introduces writing of "helper" functions.
var PROMPT = "\\$ $";
var ROOT_PROMPT = "\\# $";
var PASSWORD_PROMPT = "(?i)password:";
var NEW_PASSWORD_PROMPT = "(?i)new.*password:";
function getAttributes() {
verbose("getAttributes - starting");
// Capabilities of the system and script.
var attributes = {
CanChangeOwnPassword: true,
AdministrativeAccountSupported: true,
ProxyAccountSupported: false,
DefaultSshPort: 22,
ExpectTimeout: 10000
};
info("getAttributes - returning " + stringify(attributes));
return attributes;
}
function verifyPassword(verifyPasswordInfo) {
verbose("verifyPassword: verifyPasswordInfo = " + stringify(verifyPasswordInfo));
// Expect a shell prompt.
var matchIndex = myExpectPrompt();
if (matchIndex < 0) {
return ErrorUnexpectedResult;
}
return Success;
}
function changePassword(changePasswordInfo) {
verbose("changePassword: changePasswordInfo = " + stringify(changePasswordInfo);
// Expect a shell prompt.
var matchIndex = myExpectPrompt();
if (matchIndex < 0) {
return ErrorUnexpectedResult;
}
////////////////
// Send 'passwd' command.
verbose("Sending 'passwd' command...");
sshSend("passwd\r");
// Expect a password prompt.
matchIndex = myExpectPasswordPrompt();
if (matchIndex != 0 && matchIndex != 1) {
return ErrorUnexpectedResult;
}
////////////////
// Send the old password if needed.
if (matchIndex == 1) {
verbose("Sending old password...");
sshSend(changePasswordInfo.userPassword + "\r");
// Expect a new password prompt.
matchIndex = myExpectPasswordPrompt();
if (matchIndex != 0) {
return ErrorUnexpectedResult;
}
}
////////////////
// Send the new password.
verbose("Sending new password...");
sshSend(changePasswordInfo.newPassword + "\r");
// Expect a confirm password prompt.
matchIndex = myExpectPasswordPrompt();
if (matchIndex != 0 && matchIndex != 1) {
return ErrorUnexpectedResult;
}
////////////////
// Send new password confirmation.
verbose("Sending new password again...");
sshSend(changePasswordInfo.newPassword + "\r");
// Expect a shell prompt.
matchIndex = myExpectPrompt();
if (matchIndex < 0) {
return ErrorUncertain;
}
var status = myCheckStatusCode();
return status;
}
function setPassword(setPasswordInfo) {
verbose("setPassword: setPasswordInfo = " + stringify(setPasswordInfo));
// Expect a shell prompt.
var matchIndex = myExpectPrompt();
if (matchIndex < 0) {
return ErrorUnexpectedResult;
}
////////////////
// Send 'passwd' command.
verbose("Sending 'passwd' command...");
sshSend("passwd " + setPasswordInfo.userName + "\r");
// Expect a password prompt.
matchIndex = myExpectPasswordPrompt();
if (matchIndex != 0) {
return ErrorUnexpectedResult;
}
////////////////
// Send the new password.
verbose("Sending new password...");
sshSend(setPasswordInfo.newPassword + "\r");
// Expect a confirm password prompt.
matchIndex = myExpectPasswordPrompt();
if (matchIndex != 0 && matchIndex != 1) {
return ErrorUnexpectedResult;
}
////////////////
// Send new password confirmation.
verbose("Sending new password again...");
sshSend(setPasswordInfo.newPassword + "\r");
// Expect a shell prompt.
matchIndex = myExpectPrompt();
if (matchIndex < 0) {
return ErrorUncertain;
}
// Check the exit status code of the 'passwd' command.
var status = myCheckStatusCode();
return status;
}
function myCheckStatusCode() {
// Send command to get last status code.
verbose("Sending command to get status code...");
sshSend("echo $?\r");
// Expect command prompt.
var result = sshExpect([PROMPT, ROOT_PROMPT]);
if (result.MatchIndex < 0) {
return ErrorUncertain;
}
// Do tricky stuff to get the status code output.
var lines = result.Before.toString().replace(/\r/gm, "").replace(/^\n+/, "").replace(/\n+$/, "").split("\n");
verbose("status lines = " + stringify(lines));
var status = lines[1];
if (status != "0") {
return ErrorFailure;
}
return Success;
}
function myExpectPasswordPrompt() {
// Returns:
// -1 if there is no password prompt or shell prompt.
// 0 for a "new password" prompt.
// 1 for a "regular" password prompt.
// 2 for a regular shell prompt.
// 3 for a root shell prompt.
// Expect a password prompt.
var result = sshExpect([NEW_PASSWORD_PROMPT, PASSWORD_PROMPT, PROMPT, ROOT_PROMPT]);
return result.MatchIndex;
}
function myExpectPrompt() {
// Returns:
// -1 if there is no shell prompt.
// 0 for a regular shell prompt.
// 1 for a root shell prompt.
// Expect a shell prompt.
var result = sshExpect([PROMPT, ROOT_PROMPT]);
return result.MatchIndex;
}
As seen above, "helper" functions can be used to help organize your script and to provide functions that may be used in multiple places. In the above example, the following helper functions are defined:
- myCheckStatusCode()
- myExpectPasswordPrompt()
- myExpectPrompt()

A system may be configured with a "proxy" account for logging into the target system (this is a setting on the system's Setting tab). For accounts that are configured to use this proxy account (this is a setting on the account's Settings tab), the system uses the proxy account to log into the system, and then switch the user from the proxy account to the actual account. This feature is typically used where the target account (example: root) is not permitted to login directly with SSH. For systems set up with a custom Resource Profile, this feature may also be used to manage other types of accounts on the target system, for example a MySQL application account.
For a Resource Profile to support a proxy account:
- Have your getAttributes() function return the ProxyAccountSupported attribute as "true."
- You also need to update your verifyPassword(), changePassword(), and setPassword() functions to support proxy accounts.
- Additionally, you need to implement a switchUser() function.
When a proxy account is used, the "info" supplied to your functions include a "proxyUserName," which indicates that the system has logged in as the proxy account user. Your functions then typically need to switch the user to the target user to verify the account before changing a password. Similarly, when setting a password, you typically need to switch to the administrative account before setting the target account's password.
The switchUser() function is not used for account management - such as changing or resetting a password- but is only used when logging into the system. The function must switch the user from the proxy account to the target account (example: on Linux the script might execute "sudo bash").
The following script builds on the previous examples and demonstrates all of the functionality available with Resource Profiles:
info("+++ dev4.js loading");
// Script supporting password verification, changing own password.
// Reconciliation of out-of-sync passwords supported.
// Use of a proxy account is supported.
var PROMPT = "\\$ $";
var ROOT_PROMPT = "\\# $";
var PASSWORD_PROMPT = "(?i)password:";
var NEW_PASSWORD_PROMPT = "(?i)new.*password:";
var INVALID_PASSWORD = "(?i)incorrect password";
function getAttributes() {
verbose("getAttributes - starting");
// Capabilities of the system and script.
var attributes = {
CanChangeOwnPassword: true,
AdministrativeAccountSupported: true,
ProxyAccountSupported: true,
DefaultSshPort: 22,
ExpectTimeout: 10000
};
info("getAttributes - returning " + stringify(attributes));
return attributes;
}
function verifyPassword(verifyInfo) {
verbose("verifyPassword: verifyInfo = " + stringify(verifyInfo));
// Expect a shell prompt.
var matchIndex = myExpectPrompt();
if (matchIndex < 0) {
return ErrorUnexpectedResult;
}
// If a proxy account was used, switch to the user to verify the user.
if (verifyInfo.proxyUserName) {
// Switch to target user.
var status = mySwitchUser(verifyInfo.userName, verifyInfo.userPassword);
return status;
}
// Password is OK.
return Success;
}
function changePassword(changePasswordInfo) {
verbose("changePassword: changePasswordInfo = " + stringify(changePasswordInfo));
// Expect a shell prompt.
var matchIndex = myExpectPrompt();
if (matchIndex < 0) {
return ErrorUnexpectedResult;
}
////////////////
// Switch to the target account if needed.
var status;
if (changePasswordInfo.proxyUserName) {
status = mySwitchUser(changePasswordInfo.userName, changePasswordInfo.userPassword);
if (status != Success) {
return status;
}
}
////////////////
// Send 'passwd' command.
verbose("Sending 'passwd' command...");
sshSend("passwd\r");
// Expect a password prompt.
matchIndex = myExpectPasswordPrompt();
if (matchIndex != 0 && matchIndex != 1) {
return ErrorUnexpectedResult;
}
////////////////
// Send the old password if needed.
if (matchIndex == 1) {
verbose("Sending old password...");
sshSend(changePasswordInfo.userPassword + "\r");
// Expect a new password prompt.
matchIndex = myExpectPasswordPrompt();
if (matchIndex != 0) {
return ErrorUnexpectedResult;
}
}
////////////////
// Send the new password.
verbose("Sending new password...");
sshSend(changePasswordInfo.newPassword + "\r");
// Expect a confirm password prompt.
matchIndex = myExpectPasswordPrompt();
if (matchIndex != 0 && matchIndex != 1) {
return ErrorUnexpectedResult;
}
////////////////
// Send new password confirmation.
verbose("Sending new password again...");
sshSend(changePasswordInfo.newPassword + "\r");
// Expect a shell prompt.
matchIndex = myExpectPrompt();
if (matchIndex < 0) {
return ErrorUncertainResult;
}
status = myCheckStatusCode();
return status;
}
function setPassword(setPasswordInfo) {
verbose("setPassword: setPasswordInfo = " + stringify(setPasswordInfo));
// Expect a shell prompt.
var matchIndex = myExpectPrompt();
if (matchIndex < 0) {
return ErrorUnexpectedResult;
}
////////////////
// Switch to the admin account if needed.
var status;
if (setPasswordInfo.proxyUserName) {
status = mySwitchUser(setPasswordInfo.adminUserName, setPasswordInfo.adminPassword);
if (status == ErrorInvalidUserPassword) {
return ErrorInvalidAdminPassword;
}
if (status != Success) {
return status;
}
}
////////////////
// Send 'passwd' command.
verbose("Sending 'passwd' command...");
sshSend("passwd " + setPasswordInfo.userName + "\r");
// Expect a password prompt.
matchIndex = myExpectPasswordPrompt();
if (matchIndex != 0) {
return ErrorUnexpectedResult;
}
////////////////
// Send the new password.
verbose("Sending new password...");
sshSend(setPasswordInfo.newPassword + "\r");
// Expect a confirm password prompt.
matchIndex = myExpectPasswordPrompt();
if (matchIndex != 0 && matchIndex != 1) {
return ErrorUnexpectedResult;
}
////////////////
// Send new password confirmation.
verbose("Sending new password again...");
sshSend(setPasswordInfo.newPassword + "\r");
// Expect a shell prompt.
matchIndex = myExpectPrompt();
if (matchIndex < 0) {
return ErrorUncertainResult;
}
// Check the exit status code of the 'passwd' command.
status = myCheckStatusCode();
return status;
}
function switchUser(switchUserInfo) {
verbose("switchUser: switchUserInfo = " + stringify(switchUserInfo));
// Expect a shell prompt.
var matchIndex = myExpectPrompt();
if (matchIndex < 0) {
return ErrorUnexpectedResult;
}
// Switch to target user.
var status = mySwitchUser(switchUserInfo.userName, switchUserInfo.userPassword);
return status;
}
function mySwitchUser(userName, password) {
// su to target user.
verbose("Sending 'echo su -' command...");
sshSend("exec su - " + userName + "\r");
// Expect a password prompt or a shell prompt.
var matchIndex = myExpectPasswordPrompt();
if (matchIndex < 0) {
return ErrorUnexpectedResult;
}
////////////////
// Send the password if needed.
if (matchIndex == 1) {
verbose("Sending password...");
sshSend(password + "\r");
// Expect a new shell prompt.
var result = sshExpect([PROMPT, ROOT_PROMPT, INVALID_PASSWORD]);
if (result.MatchIndex < 0) {
return ErrorUnexpectedResult;
} else if (result.MatchIndex == 2) {
return ErrorInvalidUserPassword;
}
}
// Success.
return Success;
}
function myCheckStatusCode() {
// Send command to get last status code.
verbose("Sending command to get status code...");
sshSend("echo $?\r");
// Expect command prompt.
var result = sshExpect([PROMPT, ROOT_PROMPT]);
if (result.MatchIndex < 0) {
return ErrorUncertainResult;
}
// Do tricky stuff to get the status code output.
var lines = result.Before.toString().replace(/\r/gm, "").replace(/^\n+/, "").replace(/\n+$/, "").split("\n");
verbose("status lines = " + stringify(lines));
var status = lines[1];
if (status != "0") {
return ErrorFailure;
}
return Success;
}
function myExpectPasswordPrompt() {
// Returns:
// -1 if there is no password prompt or shell prompt.
// 0 for a "new password" prompt.
// 1 for a "regular" password prompt.
// 2 for a regular shell prompt.
// 3 for a root shell prompt.
// Expect a password prompt.
var result = sshExpect([NEW_PASSWORD_PROMPT, PASSWORD_PROMPT, PROMPT, ROOT_PROMPT]);
return result.MatchIndex;
}
function myExpectPrompt() {
// Returns:
// -1 if there is no shell prompt.
// 0 for a regular shell prompt.
// 1 for a root shell prompt.
// Expect a shell prompt.
var result = sshExpect([PROMPT, ROOT_PROMPT]);
return result.MatchIndex;
}