GUACAMOLE-514: Add guacd support for extended VNC credentials.
diff --git a/src/protocols/vnc/auth.c b/src/protocols/vnc/auth.c
index e93dbc6..0c39e94 100644
--- a/src/protocols/vnc/auth.c
+++ b/src/protocols/vnc/auth.c
@@ -31,3 +31,32 @@
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 615d80a..e978aa9 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 a21aea8..24f1ff6 100644
--- a/src/protocols/vnc/settings.c
+++ b/src/protocols/vnc/settings.c
@@ -35,7 +35,12 @@
"port",
"read-only",
"encodings",
+ "username",
"password",
+ "client-cert",
+ "client-key",
+ "ca-cert",
+ "ca-crl",
"swap-red-blue",
"color-depth",
"cursor",
@@ -109,9 +114,36 @@
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_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 @@
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 13a3d87..078f7f0 100644
--- a/src/protocols/vnc/settings.h
+++ b/src/protocols/vnc/settings.h
@@ -46,9 +46,35 @@
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 17033a6..f33b267 100644
--- a/src/protocols/vnc/vnc.c
+++ b/src/protocols/vnc/vnc.c
@@ -153,6 +153,9 @@
}
+ /* Authentication */
+ rfb_client->GetCredential = guac_vnc_get_credentials;
+
/* Password */
rfb_client->GetPassword = guac_vnc_get_password;