pamutil API
You can write programs that link against the pamutil
library. This section describes functions that are provided in the relevant .h header files. All functions return 0 on success, and non-zero on failure.
Return codes
The pamutil
library returns a 32-bit signed integer type. Strictly speaking, this type is only guaranteed to be 16 bits long, but it was retained for backwards compatibility purposes. If your compiler emits 16-bit integers, please contact support@bravurasecurity.com for a replacement that uses the long type.
The pamutil
library return codes are split into five fields to indicate problems encountered during execution, as shown below:
Bit | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 |
Field | CB | RESERVED | SPECIFIC |
Bit | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Field | GENERAL | IDAPI |
Field | Description |
---|---|
CB | Set when a password was returned from the cache instead of the Bravura Privilege server. If set, a password was returned. If unset, a password may or may not have been returned. |
RESERVED | Reserved. You may assume this field will always be 0. |
SPECIFIC | The error code in this field indicates a specific error, such as "Cannot open file for reading." |
GENERAL | The error code in this field indicates a general error, such as "Error loading creds file." |
IDAPI | The error code in this field indicates the error returned by the API Service ( |
You can use the GetErrorMessage function in the shared object, or the -v flag in runwithpass
to obtain error messages corresponding to error codes returned by pamutil
.
Error codes
# | Code | Meaning |
---|---|---|
1 | ERR_LOADING_CONFIG_FILE | Error loading config file |
2 | ERR_LOADING_CREDS_FILE | Error loading creds file |
3 | ERR_GENERATING_MACHINE_KEY | Error generating machine key |
4 | ERR_GENERATING_FILE_KEY | Error generating file key |
5 | ERR_GENERATING_ENCRYPTION_KEY | Error generating encryption key |
6 | ERR_DECRYPTING_CREDS_FILE | Error decrypting creds file |
7 | ERR_LOCKING | Error obtaining file lock |
8 | ERR_CALLING_SOAP | Error calling IDAPI service |
9 | ERR_ENCRYPTING_CREDS | Error encrypting creds file |
10 | ERR_WRITING_CREDS_FILE | Error writing to creds file |
11 | ERR_WRITING_CONFIG_FILE | Error writing to config file |
12 | ERR_UNLOCKING | Error unlocking file lock |
13 | ERR_BUILDING_COMMAND_LINE | Error building command line |
14 | ERR_RUNNING_COMMAND | Error running command |
15 | ERR_REPLACING_INPUT_FILE | Error in replace input/output file |
16 | ERR_PARSING_ARGUMENTS | Invalid arguments supplied |
17 | ERR_CREATING_ERRMSG | Error creating an error message |
18 | UNKNOWN | Unknown |
# | Code | Meaning |
---|---|---|
1 | NON_NUMERIC_INPUT_IGNOREBADSERVERCERT | Non-numeric value specified for 'ignorebadservercert' |
2 | NON_NUMERIC_INPUT_TIMEOUT | Non-numeric value specified for 'timeout' |
3 | NON_NUMERIC_INPUT_LOCKTRIES | Non-numeric value specified for 'locktries' |
4 | NON_NUMERIC_INPUT_LOCKSLEEP | Non-numeric value specified for 'locksleep' |
5 | NON_NUMERIC_INPUT_CACHESECONDS | Non-numeric value specified for 'cacheseconds' |
6 | NON_NUMERIC_INPUT_USEMACHINEKEY | Non-numeric value specified for 'usemachinekey' |
7 | NON_NUMERIC_INPUT_USEARGSKEY | Non-numeric value specified for 'useargskey' |
8 | CANNOT_OPEN_FILE_READING | Cannot open file for reading |
9 | CANNOT_OPEN_FILE_WRITING | Cannot open file for writing |
10 | CANNOT_READ_FROM_FILE | Cannot read from open file |
11 | CANNOT_CREATE_FILE | Failed to create file |
12 | CANNOT_LOCK_FILE | Failed to lock file |
13 | CANNOT_UNLOCK_FILE | Failed to unlock file |
14 | CANNOT_OPEN_DLL | Failed to load libidapi |
15 | CANNOT_LOCATE_FUNCPTR_DLL | Failed to load libidapi |
16 | MISSING_REQUIRED_KEYWORD | A required keyword was missing |
17 | INVALID_KEYWORD_ENCOUNTERED | An invalid keyword was encountered |
18 | VALUE_OUT_OF_RANGE | A numeric input value was out of range |
19 | LOCKTRIES_VALUE_OUT_OF_RANGE | The 'locktries' value was out of the acceptable range [0,200] |
20 | LOCKSLEEP_VALUE_OUT_OF_RANGE | The 'locksleep' value was out of the acceptable range [0,100000] |
21 | CACHESECONDS_VALUE_OUT_OF_RANGE | The 'cacheseconds' value was out of the acceptable range [0,86400] |
22 | TIMEOUT_VALUE_OUT_OF_RANGE | The 'timeout' value was out of the acceptable range [0,3600] |
23 | IGNOREBADSERVERCERT_VALUE_OUT_OF_RANGE | The 'ignorebadservercert' value was out of the acceptable range |
24 | USEARGSKEY_VALUE_OUT_OF_RANGE | The 'useargskey' value was out of the acceptable range |
25 | USEMACHINEKEY_VALUE_OUT_OF_RANGE | The 'usemachinekey' value was out of the acceptable range |
26 | BLANK_SYSTEM | The 'system' entry can not be blank |
27 | DUPLICATE_SYSTEM | A duplicate 'system' entry was encountered |
28 | DUPLICATE_USER | A duplicate 'user' entry was encountered |
29 | DUPLICATE_PASSWORD | A duplicate 'password' entry was encountered |
30 | DUPLICATE_PLAINTEXT | A duplicate 'plaintext' entry was encountered |
31 | DUPLICATE_EXPIRES | A duplicate 'expires' entry was encountered |
32 | DECRYPTION_FAILURE | Failed to decrypt |
33 | FAILED_IOCTL | Call to ioctl() failed |
34 | FAILED_CREATE_SOCKET | Failed to create socket |
35 | FAILED_MALLOC | Memory allocation failed |
36 | FAILED_GETKERNINFO | Call to getkerninfo() failed |
37 | FAILED_FCNTL | Call to fcntl() failed |
38 | RETRY_LIMIT_EXCEEDED | Lockfile retry limit exceeded |
39 | IMPROPER_ARGC_ARGV | Improper use of argc/argv; either null argv with positive argc or negative argc |
40 | CONFIGFILE_PATH_REQUIRED | A path to a config file is required |
41 | CREDSFILE_PATH_REQUIRED | A path to a creds file is required |
42 | LOCKFILE_PATH_REQUIRED | A path to a lock file is required |
43 | APIURL_REQUIRED | An API URL is required |
44 | NO_BYTES | An input or output buffer had no data when it was expected to contain data |
45 | UNALIGNED_CIPHERTEXT | Unaligned ciphertext |
46 | BAD_CIPHERTEXT_ENCODING | Bad ciphertext encoding |
47 | LOGIN_FAILED | Login failed |
48 | KMKEYGETBYACCOUNT_FAILED | KMKeyGetByAccount failed |
49 | NO_VALID_IFACE | No valid interface found |
50 | INCORRECT_FORMAT_DELIMETER | Delimeter expected when parsing |
51 | INCORRECT_FORMAT_KEY_VALUE | Incorrect input format, missing '=' |
52 | BUFFER_OVERRUN | A buffer was not large enough to hold the output data |
53 | SOURCE_FILE_REQUIRED | A source file must be specified |
54 | DESTINATION_FILE_REQUIRED | A destination file must be specified |
55 | SOURCE_DESTINATION_SAME | Source and destination may not be the same |
56 | SOAP_CLIENT_EXCEPTION | A SOAP client exception occurred |
57 | SOAP_CLIENT_PARSERROR_MISSING_FIELDS (deprecated: SOAP_CLIENT_INSUFFICIENT_MEMORY) | Required fields were missing from the server's response |
58 | SOAP_CLIENT_PARSERROR (deprecated: SOAP_CLIENT_INSUFFICIENT_BUFFER) | The SOAP client failed to parse the server's response |
59 | SOAP_CLIENT_FAILED_TO_SEND_REQUEST | The SOAP client failed to send the request |
60 | SPECIFIC_OUT_OF_RANGE | The specific error code was either negative or larger than the largest known code. |
61 | GENERAL_OUT_OF_RANGE | The general error code was either negative or larger than the largest known code. |
62 | UNKNOWN | Unknown/OS error; consult logs for more information |
63 | ENCRYPTION_FAILURE | Failed to encrypt |
64 | FAILED_GET_SEMAPHORE | Failed acquiring semaphore |
65 | FAILED_RELEASE_SEMAPHORE | Failed releasing semaphore |
66 | USER_EMPTY | The user field was empty |
67 | PASSWORD_EMPTY | The password field was empty |
68 | MANAGEDACCOUNTRANDOMIZEPASSWORD_FAILED | ManagedAccountRandomizePassword failed |
69 | MANAGEDACCOUNTOVERRIDEPASSWORD_FAILED | ManagedAccountOverridePassword failed |
70 | MANAGEDACCOUNTRANDOMIZEPASSWORD_MULTIPLE_RES | ManagedAccountRandomizePassword returned multiple results |
71 | MANAGEDACCOUNTOVERRIDEPASSWORD_MULTIPLE_RES | ManagedAccountOverridePassword returned multiple results |
72 | NON_NUMERIC_INPUT_SYNCHRONOUSWRITE | Non-numeric value specified for 'synchronouswrite' |
73 | LARGECREDENTIALGET_FAILED | LargeCredentialGet failed |
74 | LCINFOFILE_PATH_REQUIRED | A path to a large creds info file is required |
75 | DUPLICATE_ATTRKEY | A duplicate 'attrkey' entry was encountered |
76 | DUPLICATE_FILENAME | A duplicate 'filename' entry was encountered |
77 | DUPLICATE_LCHASH | A duplicate 'lchash' entry was encountered |
Common return values
Below are some error codes of note, either because they are commonly encountered or should be handled by scripts:
Code | Meaning | Notes |
---|---|---|
0 | No errors. A fresh password was retrieved from the Bravura Privilege server. | |
-2147483648 | No errors. A password was retrieved from the cache. | Since the password was retrieved from the cache, there is a chance that it is now incorrect. Be prepared to retry any operations involving this password. Do not proceed on this error code if your application cannot tolerate incorrect passwords. In such cases, you should use the expirecache argument to prevent usage of the cache. |
-2097119174 | Error calling KMKeyGetByAccount on the API Service. The API Service returned 58 (ERR_PASSWORD_CHANGE_IMMINENT). A cached password was retrieved. | The Bravura Privilege server is currently in the process of changing the requested password and the cache is likely to be stale now or in the very near future. Your application should wait and retry. Do not use the cached password unless it is critical that execution proceed. |
50364474 | Error calling KMKeyGetByAccount on the API Service. The API Service returned 58 (ERR_PASSWORD_CHANGE_IMMINENT). A cached password was not retrieved. | The Bravura Privilege server is currently in the process of changing the requested password and the cache has expired. Your application must wait and retry. |
61898752 | Error calling the API Service. There was an error attempting to send the SOAP request. A cached password was not retrieved. | Typically this error is caused by a network problem; for example, if |
33579008 | Failed to decrypt a password in the creds file. A cached password was not retrieved. | This error can be caused by changes in the composite key, or tampering of the creds file. |
-2098167805 | Error logging in to the API Service. The API Service returned error code 3 (ERR_NOT_LOGGED_IN). A cached password was retrieved. | The API user credentials were successfully decrypted (or were not encrypted) but were rejected by the API Service. If the password in the creds file has not recently changed, immediate action should be taken. This error may mean that your API account has been compromised. |
49315843 | Error logging in to the API Service. The API Service returned error code 3 (ERR_NOT_LOGGED_IN). A cached password was not retrieved. | The API user credentials were successfully decrypted (or were not encrypted) but were rejected by the API Service. If this instance of |
39874560 | Retry limit exceeded when trying to lock the lock file. A cached password was not retrieved. | This error may occur when multiple |
-2107609088 | Retry limit exceeded when trying to lock the lock file. A cached password was retrieved. | Same as above. |
72384698 | Error calling ManagedAccountOverridePassword on the IDAPI service. The API Service returned 186 (ERR_PASSWORD_FAILED_STRENGTH_CHECK) | The password the user specified did not meet the complexity requirements for this account and was rejected. |
Functions
GetPamUtilConfig
To obtain information from the configuration file.
int GetPamUtilConfig( const char* cfgFilePath, struct PamUtilConfig** config );
where:
cfgFilePath [in]: File name to open and read configuration settings from
config [out]: Pointer to a pointer that will point to the allocated PamUtilConfig struct
This function parses the configuration file and returns its content in a PamUtilConfig struct. The struct is allocated so you must call FreePamUtilConfig when you have finished with struct.
FreePamUtilConfig
Clear the struct allocated by GetPamUtilConfig.
int FreePamUtilConfig( struct PamUtilConfig* config);
where:
config [in]: Pointer that was allocated by GetPamUtilConfig
GetPassword
To obtain a password from the cache and/or web service, with full locking, caching and OTP management semantics:
int GetPassword( const char* cfgFilePath, char* errmsg, unsigned int errmsg_bufsz, int expirecache, const char* resourceId, const char* accountId, int argc, char** argv, const char* userkey, char* password, unsigned int password_bufsz );
where:
cfgFilePath [in]: File name to open and read configuration settings from
errmsg [out]: Pointer to a buffer to place an error message in
errmsg_bufsz [in]: Size of the errmsg buffer
expirecache [in]: Whether to treat the cache as expired and force a fetch of the password
resourceId [in]: Name of the managed system to retrieve a password for
accountId [in]: Name of the account to retrieve a password for
argc [in]: The number of elements in argv. Ignored if useargskey=0
argv [in]: An array of null-terminated strings which will be incorporated into the encryption key. Ignored if useargskey=0
userkey [in]: An unencrypted null-terminated string to add to the encryption key
password [out]: Pointer to a buffer to place the retrieved password in
password_bufsz [in]: Size of the password buffer
Bravura Security recommends that you always place command-line arguments for programs using the pamutil
shared library in the argc and argv parameters, even if you don’t intend to use them. If useargskey is unset in config.ini, the library will ignore these parameters. You can subsequently enable the useargskey option without needing to recompile the program.
RandomizePassword
To set the password of an account to a random value.
int RandomizePassword( const char* cfgFilePath, char* errmsg, unsigned int errmsg_size, const char* resourceId, const char* accountId, int argc, char** argv, const char* userkey );
where:
cfgFilePath [in]: File name to open and read configuration settings from
errmsg [out]: Pointer to a buffer to place an error message in
errmsg_bufsz [in]: Size of the errmsg buffer
resourceId [in]: Name of the managed system to retrieve a password for
accountId [in]: Name of the account to retrieve a password for
argc [in]: The number of elements in argv. Ignored if useargskey=0
argv [in]: An array of null-terminated strings which will be incorporated into the encryption key. Ignored if useargskey=0
userkey [in]: An unencrypted null-terminated string to add to the encryption key
Bravura Security recommends that you always place command-line arguments for programs using the pamutil
shared library in the argc and argv parameters, even if you don’t intend to use them. If useargskey is unset in config.ini, the library will ignore these parameters. You can subsequently enable the useargskey option without needing to recompile the program.
OverridePassword
To set the password of an account to a specified value.
int OverridePassword( const char* cfgFilePath, char* errmsg, unsigned int errmsg_size, const char* resourceId, const char* accountId, const char* overridenPassword, int argc, char** argv, const char* userkey );
where:
cfgFilePath [in]: File name to open and read configuration settings from
errmsg [out]: Pointer to a buffer to place an error message in
errmsg_bufsz [in]: Size of the errmsg buffer
resourceId [in]: Name of the managed system to retrieve a password for
accountId [in]: Name of the account to retrieve a password for
overridenPassword [in]: The specified value to set the password as
argc [in]: The number of elements in argv. Ignored if useargskey=0
argv [in]: An array of null-terminated strings which will be incorporated into the encryption key. Ignored if useargskey=0
userkey [in]: An unencrypted null-terminated string to add to the encryption key
Bravura Security recommends that you always place command-line arguments for programs using the pamutil
shared library in the argc and argv parameters, even if you don’t intend to use them. If useargskey is unset in config.ini, the library will ignore these parameters. You can subsequently enable the useargskey option without needing to recompile the program.
SetInitialPasswords
To set initial passwords as encrypted in the creds.ini file.
int SetInitialPasswords( const char* cfgFilePath,- const char* userkey, const char* adminid, const char* adminpw, const char* proxyid, const char* proxypw, int argc, char** argv, char* errmsg, unsigned int errmsg_bufsz );
where:
cfgFilePath [in]: File name to open and read config settings from
userkey [in]: An unencrypted null-terminated string to add to the encryption key
adminid [in]: An unencrypted null-terminated string to set the __OTP__ credential ID to
adminpw [in]: An unencrypted null-terminated string to set the __OTP__ credential password to
proxyid [in]: An unencrypted null-terminated string to set the __PROXY__ credential ID
proxypw [in]: An unencrypted null-terminated string to set the __PROXY__ credential password to
argc [in]: The number of elements in argv. Ignored if useargskey=0
argv [in]: An array of null-terminated strings which will be incorporated into the encryption key. Ignored if useargskey=0
errmsg [out]: Pointer to a buffer to place an error message in
errmsg_bufsz [in]: Size of the errmsg buffer
GetErrorMessage
To obtain a complete error message from a pamutil
return code, including whether the password was cached and the IDAPI error number:
int GetErrorMessage( int error, char* output, unsigned int outputlen );
where:
error [in]: The error returned by
pamutil
output [out]: Pointer to a buffer to place the error message in
outputlen [in]: Size of the error message buffer
Returns a pamutil
error code with only specific and general fields set.
GetSpecificErrorMessage
To obtain the specific error message from a pamutil
return code:
const char* GetSpecificErrorMessage( int error);
where:
error [in]: The error returned by
pamutil
Returns a pointer to the error message associated with the specific field of error (ignoring all other fields), or null if there is no message associated with that code.
GetGeneralErrorMessage
To obtain a general error message from a pamutil
return code:
const char* GetGeneralErrorMessage( int error);
where:
error [in]: The error returned by
pamutil
Returns a pointer to the error message associated with the general field of error (ignoring all other fields), or null if there is no message associated with that code.
You do not need to free the returned string from either GetSpecificErrorMessage or GetGeneralErrorMessage.
The error messages returned by GetGeneralErrorMessage and GetSpecificErrorMessage are the same as those used by GetErrorMessage, except it dynamically creates an error message using every field of the error code, thus requires an output buffer to be allocated by the caller and may fail if this buffer is not large enough. You can use GetSpecificErrorMessage to determine why GetErrorMessage failed. A common error is "53547008: insufficient output buffer size".