wolfSSH User Authentication Callback
wolfSSH needs to be able to authenticate users connecting to the server no matter which environment the library is embedded. Lookups may need to be done using passwords or RSA public keys stored in a text file, database, or hard coded into the application.
wolfSSH provides a callback hook that receives the username, either the password or public key provided in the user authentication message and the requested authentication type. The callback function then performs the appropriate lookups and gives a reply. Providing a callback is required.
The callback should return one of several failures or a success. The library will treat all the failures the same except for logging purposes, i.e. return the User Authorization Failure message to the client who will try again.
For password lookups, the plaintext password is given to the callback function. The username and password should be checked and if they match, a success returned. On success, the SSH handshake continues immediately. Password changing is not supported at this time.
For public key lookups, the public key blob from the client is given to the callback function. The public key is checked against the server’s list of valid client public keys. If the public key provided matches the known public key for that user. The wolfSSH library performs the actual validation of the user authentication signature following the process described in RFC 4252 §7.
Commonly for public keys, the server stores either the users’ public keys as generated by the ssh-keygen utility or stores a fingerprint of the public key. This value for a user is what is compared. The client will provide a signature of the session ID and the user authentication request message using its private key; the server verifies this signature using the public key.
Callback Function Prototype
The prototype for the user authentication callback function is:
int UserAuthCb(byte authType , const WS_UserAuthData*
authData , void* ctx );
This function prototype is of the type:
WS_CallbackUserAuth
The parameter authType
is either:
WOLFSSH_USERAUTH_PASSWORD
or
WOLFSSH_USERAUTH_PUBLICKEY
The parameter, authData, is a pointer to the authentication data.
See section 5.4 for a description of WS_UserAuthData
The parameter ctx is an application defined context; wolfSSH does nothing with and knows nothing about the data in the context, it only provides the context pointer to the callback function.
Callback Function Authentication Type Constants
The following are values passed to the user authentication callback function in the authType
parameter. It guides the callback function as to the type of authentication data to check. A system could use either a password or public key for different users.
WOLFSSH_USERAUTH_PASSWORD
WOLFSSH_USERAUTH_PUBLICKEY
Callback Function Return Code Constants
The following are the return codes the callback function shall return to the library. The failure code indicates that nothing was done and the callback couldn’t do any checking.
The invalid codes indicate why the user authentication is being rejected:
invalid username
invalid password
invalid public key
The server indicates success or failure to the client, the specific failure type is only used for logging. There is a special success and failure response the callback can return to the library, partial-success. This means the authentication type was successful, but another authentication type is still required to fully authenticate. The server will send a user authentication failure message with the partial-success flag set to client.
WOLFSSH_USERAUTH_SUCCESS
WOLFSSH_USERAUTH_FAILURE
WOLFSSH_USERAUTH_INVALID_USER
WOLFSSH_USERAUTH_INVALID_PASSWORD
WOLFSSH_USERAUTH_INVALID_PUBLICKEY
WOLFSSH_USERAUTH_PARTIAL_SUCCESS
Callback Function Data Types
The client data is passed to the callback function in a structure called WS_UserAuthData
. It contains pointers to the data in the message. Common fields are in this structure. Method specific fields are in a union of structures in the user authentication data.
typedef struct WS_UserAuthData {
byte authType ;
byte* username ;
word32 usernameSz ;
byte* serviceName ;
word32 serviceNameSz ; n
union {
WS_UserAuthData_Password password ;
WS_UserAuthData_PublicKey publicKey ;
} sf;
} WS_UserAuthData;
Password
The username
and usernameSz
parameters are the username provided by the client and its size in octets.
The password
and passwordSz
fields are the client’s password and its size in octets.
While set if provided by the client, the parameters hasNewPassword
, newPassword
, and newPasswordSz
are not used. There is no mechanism to tell the client to change its password at this time.
typedef struct WS_UserAuthData_Password {
uint8_t* password ;
uint32_t passwordSz ;
uint8_t hasNewPasword ;
uint8_t* newPassword ;
uint32_t newPasswordSz ;
} WS_UserAuthData_Password;
Public Key
wolfSSH will support multiple public key algorithms. The publicKeyType member points to the algorithm name used.
The publicKey field points at the public key blob provided by the client.
The public key checking will have either one or two steps. First, if the hasSignature
field is not set, there is no signature. Only verify the username
and publicKey
are expected. This step is optional depending on client configuration, and can save from doing costly public key operations with an invalid user. Second, the hasSignature
field is set and signature field points to the client signature. Again the username
and publicKey
should be checked. wolfSSH will automatically check the signature.
Each of the fields has a size value in octets.
typedef struct WS_UserAuthData_PublicKey {
byte* publicKeyType;
word32 publicKeyTypeSz;
byte* publicKey;
word32 publicKeySz;
byte hasSignature;
byte* signature;
word32 signatureSz;
} WS_UserAuthData_PublicKey;