Skip to content

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 library indicates only success or failure to the client, the specific failure type is only used for logging.

WOLFSSH_USERAUTH_SUCCESS
WOLFSSH_USERAUTH_FAILURE
WOLFSSH_USERAUTH_INVALID_USER
WOLFSSH_USERAUTH_INVALID_PASSWORD
WOLFSSH_USERAUTH_INVALID_PUBLICKEY

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 passwordand 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;