Skip to content

Commit f0ca173

Browse files
committed
test: add ARD auth probe client
1 parent c80fc70 commit f0ca173

2 files changed

Lines changed: 158 additions & 1 deletion

File tree

CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ endif(X11_xcb_FOUND AND X11_xcb_xtest_FOUND AND X11_xcb_keysyms_FOUND)
604604

605605
set(LIBVNCCLIENT_EXAMPLES
606606
backchannel
607+
ardauthprobe
607608
ppmtest
608609
)
609610

@@ -652,7 +653,11 @@ if(WITH_EXAMPLES)
652653

653654
if(WITH_LIBVNCCLIENT)
654655
foreach(e ${LIBVNCCLIENT_EXAMPLES})
655-
add_executable(client_examples_${e} ${LIBVNCCLIEXAMPLE_DIR}/${e}.c ${LIBVNCCLIEXAMPLE_DIR}/${${e}_EXTRA_SOURCES} )
656+
if(EXISTS ${TESTS_DIR}/${e}.c)
657+
add_executable(client_examples_${e} ${TESTS_DIR}/${e}.c ${LIBVNCCLIEXAMPLE_DIR}/${${e}_EXTRA_SOURCES} )
658+
else()
659+
add_executable(client_examples_${e} ${LIBVNCCLIEXAMPLE_DIR}/${e}.c ${LIBVNCCLIEXAMPLE_DIR}/${${e}_EXTRA_SOURCES} )
660+
endif()
656661
set_target_properties(client_examples_${e} PROPERTIES OUTPUT_NAME ${e})
657662
set_target_properties(client_examples_${e} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/examples/client)
658663
target_link_libraries(client_examples_${e} vncclient ${CMAKE_THREAD_LIBS_INIT} ${SDL2_LIBRARY} ${GTK2_LIBRARIES} ${FFMPEG_LIBRARIES} ${LIBSSHTUNNEL_LIBRARY})

test/ardauthprobe.c

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/**
2+
* @example ardauthprobe.c
3+
*
4+
* Headless ARD auth probe client for testing one forced security type at a
5+
* time against a remote Screen Sharing / ARD server.
6+
*
7+
* Usage:
8+
* VNC_USER=<username> VNC_PASS=<password> \
9+
* ./ardauthprobe -auth <security-type> <host[:port]>
10+
*
11+
* Optional Kerberos overrides for auth type 35:
12+
* VNC_ARD_REALM=<realm>
13+
* VNC_ARD_CLIENT_PRINCIPAL=<client-principal>
14+
* VNC_ARD_SERVICE_PRINCIPAL=<service-principal>
15+
*
16+
* Example:
17+
* VNC_USER=alex VNC_PASS=secret \
18+
* ./ardauthprobe -auth 33 Alexs-Mac-mini.local:5900
19+
*
20+
* ARD auth type samples:
21+
* -auth 30 ARD DH
22+
* -auth 33 ARD RSA-SRP
23+
* -auth 35 ARD Kerberos GSS-API
24+
* -auth 36 ARD Direct SRP
25+
*
26+
* Kerberos sample:
27+
* VNC_USER=alex VNC_PASS=secret \
28+
* VNC_ARD_REALM='LKDC:SHA1.XXXXXX' \
29+
* VNC_ARD_SERVICE_PRINCIPAL='vnc/LKDC:SHA1.XXXXXX@LKDC:SHA1.XXXXXX' \
30+
* ./ardauthprobe -auth 35 Alexs-Mac-mini.local:5900
31+
*
32+
* On success the probe prints one AUTH_OK line with the requested and selected
33+
* auth schemes plus the negotiated desktop name and size, then exits.
34+
*/
35+
36+
#include <rfb/rfbclient.h>
37+
38+
#include <stdio.h>
39+
#include <stdlib.h>
40+
#include <string.h>
41+
42+
static void HandleRect(rfbClient *client, int x, int y, int w, int h) {
43+
(void)client;
44+
(void)x;
45+
(void)y;
46+
(void)w;
47+
(void)h;
48+
}
49+
50+
static rfbCredential *GetCredential(rfbClient *client, int credentialType) {
51+
const char *user = getenv("VNC_USER");
52+
const char *pass = getenv("VNC_PASS");
53+
rfbCredential *cred = NULL;
54+
55+
(void)client;
56+
if (credentialType != rfbCredentialTypeUser)
57+
return NULL;
58+
if (!user || !pass) {
59+
rfbClientErr("Set VNC_USER and VNC_PASS in the environment.\n");
60+
return NULL;
61+
}
62+
63+
cred = (rfbCredential *)calloc(1, sizeof(*cred));
64+
if (!cred)
65+
return NULL;
66+
cred->userCredential.username = strdup(user);
67+
cred->userCredential.password = strdup(pass);
68+
if (!cred->userCredential.username || !cred->userCredential.password) {
69+
free(cred->userCredential.username);
70+
free(cred->userCredential.password);
71+
free(cred);
72+
return NULL;
73+
}
74+
return cred;
75+
}
76+
77+
/*
78+
* Kerberos-based ARD auth needs more than a username/password pair. These
79+
* environment variables let the probe supply the same realm/principal data we
80+
* discover externally from Keychain or prior captures without hardcoding it.
81+
*/
82+
static void ApplyOptionalKerberosConfig(rfbClient *client) {
83+
const char *realm = getenv("VNC_ARD_REALM");
84+
const char *client_principal = getenv("VNC_ARD_CLIENT_PRINCIPAL");
85+
const char *service_principal = getenv("VNC_ARD_SERVICE_PRINCIPAL");
86+
87+
if (realm && *realm)
88+
rfbClientSetARDAuthRealm(client, realm);
89+
if (client_principal && *client_principal)
90+
rfbClientSetARDAuthClientPrincipal(client, client_principal);
91+
if (service_principal && *service_principal)
92+
rfbClientSetARDAuthServicePrincipal(client, service_principal);
93+
}
94+
95+
static int ParseAuthType(const char *value, uint32_t *out) {
96+
char *end = NULL;
97+
unsigned long parsed = 0;
98+
99+
if (!value || !out)
100+
return 0;
101+
parsed = strtoul(value, &end, 0);
102+
if (!end || *end != '\0' || parsed > 255)
103+
return 0;
104+
*out = (uint32_t)parsed;
105+
return 1;
106+
}
107+
108+
int main(int argc, char **argv) {
109+
rfbClient *client = NULL;
110+
uint32_t auth_types[2] = {0, 0};
111+
int init_argc = 2;
112+
char *init_argv[3] = {NULL, NULL, NULL};
113+
114+
if (argc < 3 || strcmp(argv[1], "-auth") != 0 ||
115+
!ParseAuthType(argv[2], &auth_types[0])) {
116+
fprintf(stderr, "usage: %s -auth <security-type> <host[:port]>\n",
117+
argv[0]);
118+
return 2;
119+
}
120+
121+
client = rfbGetClient(8, 3, 4);
122+
if (!client) {
123+
fprintf(stderr, "failed to create VNC client\n");
124+
return 1;
125+
}
126+
127+
client->GotFrameBufferUpdate = HandleRect;
128+
client->GetCredential = GetCredential;
129+
ApplyOptionalKerberosConfig(client);
130+
131+
/* Restrict negotiation to the requested auth type so each probe run
132+
* answers one concrete question about server compatibility. */
133+
SetClientAuthSchemes(client, auth_types, -1);
134+
135+
init_argv[0] = argv[0];
136+
init_argv[1] = argv[3];
137+
138+
if (!rfbInitClient(client, &init_argc, init_argv)) {
139+
rfbClientCleanup(client);
140+
return 1;
141+
}
142+
143+
fprintf(stderr,
144+
"AUTH_OK requested=%u selected=%u subauth=%u desktop=\"%s\" "
145+
"size=%dx%d\n",
146+
auth_types[0], client->authScheme, client->subAuthScheme,
147+
client->desktopName ? client->desktopName : "",
148+
client->width, client->height);
149+
150+
rfbClientCleanup(client);
151+
return 0;
152+
}

0 commit comments

Comments
 (0)