diff --git a/src/protocols/vnc/auth.c b/src/protocols/vnc/auth.c index e93dbc66..0c39e94c 100644 --- a/src/protocols/vnc/auth.c +++ b/src/protocols/vnc/auth.c @@ -31,3 +31,32 @@ char* guac_vnc_get_password(rfbClient* client) { return ((guac_vnc_client*) gc->data)->settings->password; } +rfbCredential* guac_vnc_get_credentials(rfbClient* client, int credentialType) { + guac_client* gc = rfbClientGetClientData(client, GUAC_VNC_CLIENT_KEY); + rfbCredential *creds = malloc(sizeof(rfbCredential)); + + if (credentialType == rfbCredentialTypeUser) { + creds->userCredential.username = ((guac_vnc_client*) gc->data)->settings->username; + creds->userCredential.password = ((guac_vnc_client*) gc->data)->settings->password; + return creds; + } + + else if (credentialType == rfbCredentialTypeX509) { + creds->x509Credential.x509ClientCertFile = ((guac_vnc_client*) gc->data)->settings->client_cert; + creds->x509Credential.x509ClientKeyFile = ((guac_vnc_client*) gc->data)->settings->client_key; + creds->x509Credential.x509CACertFile = ((guac_vnc_client*) gc->data)->settings->ca_cert; + creds->x509Credential.x509CACRLFile = ((guac_vnc_client*) gc->data)->settings->ca_crl; + + if (creds->x509Credential.x509CACRLFile != NULL) + creds->x509Credential.x509CrlVerifyMode = 2; + else + creds->x509Credential.x509CrlVerifyMode = 0; + + return creds; + } + + guac_client_log(client, GUAC_LOG_ERROR, + "Unknown credential type requested."); + return NULL; + +} diff --git a/src/protocols/vnc/auth.h b/src/protocols/vnc/auth.h index 615d80a1..e978aa95 100644 --- a/src/protocols/vnc/auth.h +++ b/src/protocols/vnc/auth.h @@ -27,7 +27,7 @@ /** * Callback which is invoked by libVNCServer when it needs to read the user's - * VNC password. As ths user's password, if any, will be stored in the + * VNC password. As this user's password, if any, will be stored in the * connection settings, this function does nothing more than return that value. * * @param client @@ -38,5 +38,19 @@ */ char* guac_vnc_get_password(rfbClient* client); +/** + * Callback which is invoked by libVNCServer when it needs to read the user's + * VNC credentials. The credentials are stored in the connection settings, + * so they will be retrieved from that. + * + * @param client + * The rfbClient associated with the VNC connection requiring the + * authentication. + * + * @return + * The rfbCredential object that contains the required credentials. + */ +rfbCredential* guac_vnc_get_credentials(rfbClient* client, int credentialType); + #endif diff --git a/src/protocols/vnc/settings.c b/src/protocols/vnc/settings.c index a21aea8c..24f1ff61 100644 --- a/src/protocols/vnc/settings.c +++ b/src/protocols/vnc/settings.c @@ -35,7 +35,12 @@ const char* GUAC_VNC_CLIENT_ARGS[] = { "port", "read-only", "encodings", + "username", "password", + "client-cert", + "client-key", + "ca-cert", + "ca-crl", "swap-red-blue", "color-depth", "cursor", @@ -108,10 +113,37 @@ enum VNC_ARGS_IDX { */ IDX_ENCODINGS, + /** + * The username to send to the VNC server if authentication is requested. + */ + IDX_USERNAME, + /** * The password to send to the VNC server if authentication is requested. */ IDX_PASSWORD, + + /** + * The client certificate to send to the VNC server if x509 authentication + * is being used. + */ + IDX_CLIENT_CERT, + + /** + * The client private key to send to the VNC server if x509 authentication + * is being used. + */ + IDX_CLIENT_KEY, + + /** + * The CA certificate to use when performing x509 authentication. + */ + IDX_CA_CERT, + + /** + * The location of the CA CRL to use when performing x509 authentication. + */ + IDX_CA_CRL, /** * "true" if the red and blue components of each color should be swapped, @@ -337,10 +369,30 @@ guac_vnc_settings* guac_vnc_parse_args(guac_user* user, guac_user_parse_args_int(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_PORT, 0); + settings->username = + guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, + IDX_USERNAME, ""); /* NOTE: freed by libvncclient */ + settings->password = guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, IDX_PASSWORD, ""); /* NOTE: freed by libvncclient */ + settings->client_cert = + guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, + IDX_CLIENT_CERT, NULL); + + settings->client_key = + guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, + IDX_CLIENT_KEY, NULL); + + settings->ca_cert = + guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, + IDX_CA_CERT, NULL); + + settings->ca_crl = + guac_user_parse_args_string(user, GUAC_VNC_CLIENT_ARGS, argv, + IDX_CA_CRL, NULL); + /* Remote cursor */ if (strcmp(argv[IDX_CURSOR], "remote") == 0) { guac_user_log(user, GUAC_LOG_INFO, "Cursor rendering: remote"); @@ -530,6 +582,10 @@ void guac_vnc_settings_free(guac_vnc_settings* settings) { free(settings->hostname); free(settings->recording_name); free(settings->recording_path); + free(settings->client_cert); + free(settings->client_key); + free(settings->ca_cert); + free(settings->ca_crl); #ifdef ENABLE_VNC_REPEATER /* Free VNC repeater settings */ diff --git a/src/protocols/vnc/settings.h b/src/protocols/vnc/settings.h index 13a3d87b..078f7f0c 100644 --- a/src/protocols/vnc/settings.h +++ b/src/protocols/vnc/settings.h @@ -45,10 +45,36 @@ typedef struct guac_vnc_settings { */ int port; + /** + * The username given in the arguments. + */ + char* username; + /** * The password given in the arguments. */ char* password; + + /** + * The client certificate to use for authentication. + */ + char* client_cert; + + /** + * The client private key to use for authentication. + */ + char* client_key; + + /** + * The CA certificate file to use for authentication. + */ + char* ca_cert; + + /** + * The CA CRL location to use for checking for revoked certificates during + * authentication. + */ + char* ca_crl; /** * Space-separated list of encodings to use within the VNC session. diff --git a/src/protocols/vnc/vnc.c b/src/protocols/vnc/vnc.c index 17033a67..f33b267a 100644 --- a/src/protocols/vnc/vnc.c +++ b/src/protocols/vnc/vnc.c @@ -153,6 +153,9 @@ rfbClient* guac_vnc_get_client(guac_client* client) { } + /* Authentication */ + rfb_client->GetCredential = guac_vnc_get_credentials; + /* Password */ rfb_client->GetPassword = guac_vnc_get_password;