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;