Skip to content

Commit 1db03a5

Browse files
committed
Add new auth SASL2 syntax tests
1 parent e691abc commit 1db03a5

3 files changed

Lines changed: 356 additions & 0 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ tests/test_md5
6464
tests/test_rand
6565
tests/test_resolver
6666
tests/test_sasl
67+
tests/test_sasl2_syntax
6768
tests/test_scram
6869
tests/test_send_queue
6970
tests/test_serialize_sm

Makefile.am

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ STATIC_TESTS = \
190190
tests/test_jid \
191191
tests/test_ctx \
192192
tests/test_sasl \
193+
tests/test_sasl2_syntax \
193194
tests/test_send_queue \
194195
tests/test_serialize_sm \
195196
tests/test_string \
@@ -270,6 +271,15 @@ tests_test_sasl_SOURCES = tests/test_sasl.c src/sasl.c \
270271
src/crypto.c src/hash.c src/jid.c src/md5.c src/scram.c src/sha1.c src/sha256.c src/sha512.c src/snprintf.c src/util.c
271272
tests_test_sasl_CFLAGS = -I$(top_srcdir)/src
272273

274+
tests_test_sasl2_syntax_SOURCES = tests/test_sasl2_syntax.c src/stanza.c src/util.c src/jid.c src/snprintf.c src/hash.c src/md5.c src/sha1.c src/sha256.c src/sha512.c src/crypto.c src/rand.c src/scram.c src/sasl.c
275+
tests_test_sasl2_syntax_CFLAGS = $(STROPHE_FLAGS) -I$(top_srcdir)/src $(PARSER_CFLAGS)
276+
if PARSER_EXPAT
277+
tests_test_sasl2_syntax_SOURCES += src/parser_expat.c
278+
else
279+
tests_test_sasl2_syntax_SOURCES += src/parser_libxml2.c
280+
endif
281+
tests_test_sasl2_syntax_LDADD = $(PARSER_LIBS)
282+
273283
tests_test_scram_SOURCES = tests/test_scram.c tests/test.c src/sha1.c \
274284
src/sha256.c src/sha512.c
275285
tests_test_scram_CFLAGS = $(STROPHE_FLAGS) -I$(top_srcdir)/src

tests/test_sasl2_syntax.c

Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
/* SPDX-License-Identifier: MIT OR GPL-3.0-only */
2+
/* test_sasl2_syntax.c
3+
** libstrophe XMPP client library -- test routines for SASL2 syntax
4+
**
5+
** Copyright (C) 2024-2026 libstrophe contributors
6+
**
7+
** This software is provided AS-IS with no warranty, either express
8+
** or implied.
9+
**
10+
** This program is dual licensed under the MIT or GPLv3 licenses.
11+
*/
12+
13+
#include <stdio.h>
14+
#include <stdlib.h>
15+
#include <string.h>
16+
#include <assert.h>
17+
18+
#include "strophe.h"
19+
#include "common.h"
20+
#include "sasl.h"
21+
#include "scram.h"
22+
#include "test.h"
23+
24+
/* stubs to build test without whole libstrophe */
25+
26+
static xmpp_stanza_t *last_sent_stanza = NULL;
27+
28+
void send_stanza(xmpp_conn_t *conn,
29+
xmpp_stanza_t *stanza,
30+
xmpp_send_queue_owner_t owner)
31+
{
32+
(void)conn;
33+
(void)owner;
34+
if (last_sent_stanza)
35+
xmpp_stanza_release(last_sent_stanza);
36+
last_sent_stanza = xmpp_stanza_copy(stanza);
37+
xmpp_stanza_release(stanza);
38+
}
39+
40+
void handler_add(xmpp_conn_t *conn,
41+
xmpp_handler handler,
42+
const char *ns,
43+
const char *name,
44+
const char *type,
45+
void *userdata)
46+
{
47+
(void)conn;
48+
(void)handler;
49+
(void)ns;
50+
(void)name;
51+
(void)type;
52+
(void)userdata;
53+
}
54+
55+
void conn_disconnect(xmpp_conn_t *conn)
56+
{
57+
(void)conn;
58+
}
59+
60+
int xmpp_conn_is_secured(xmpp_conn_t *conn)
61+
{
62+
(void)conn;
63+
return 0;
64+
}
65+
66+
tls_t *tls_new(xmpp_conn_t *conn)
67+
{
68+
(void)conn;
69+
return NULL;
70+
}
71+
72+
void tls_free(tls_t *tls)
73+
{
74+
(void)tls;
75+
}
76+
77+
void tls_clear_password_cache(xmpp_conn_t *conn)
78+
{
79+
(void)conn;
80+
}
81+
82+
int tls_init_channel_binding(tls_t *tls,
83+
const char **binding_prefix,
84+
size_t *binding_prefix_len)
85+
{
86+
(void)tls;
87+
(void)binding_prefix;
88+
(void)binding_prefix_len;
89+
return 0;
90+
}
91+
92+
const void *tls_get_channel_binding_data(tls_t *tls, size_t *size)
93+
{
94+
(void)tls;
95+
(void)size;
96+
return NULL;
97+
}
98+
99+
char *tls_id_on_xmppaddr(xmpp_conn_t *conn, unsigned int n)
100+
{
101+
(void)conn;
102+
(void)n;
103+
return NULL;
104+
}
105+
106+
unsigned int tls_id_on_xmppaddr_num(xmpp_conn_t *conn)
107+
{
108+
(void)conn;
109+
return 0;
110+
}
111+
112+
void handler_reset_timed(xmpp_conn_t *conn, int user_only)
113+
{
114+
(void)conn;
115+
(void)user_only;
116+
}
117+
118+
void handler_add_timed(xmpp_conn_t *conn,
119+
xmpp_timed_handler handler,
120+
unsigned long period,
121+
void *userdata)
122+
{
123+
(void)conn;
124+
(void)handler;
125+
(void)period;
126+
(void)userdata;
127+
}
128+
129+
void handler_add_id(xmpp_conn_t *conn,
130+
xmpp_handler handler,
131+
const char *id,
132+
void *userdata)
133+
{
134+
(void)conn;
135+
(void)handler;
136+
(void)id;
137+
(void)userdata;
138+
}
139+
140+
void xmpp_timed_handler_delete(xmpp_conn_t *conn, xmpp_timed_handler handler)
141+
{
142+
(void)conn;
143+
(void)handler;
144+
}
145+
146+
void xmpp_disconnect(xmpp_conn_t *conn)
147+
{
148+
(void)conn;
149+
}
150+
151+
void conn_prepare_reset(xmpp_conn_t *conn, xmpp_open_handler handler)
152+
{
153+
(void)conn;
154+
(void)handler;
155+
puts("should not reset connection in SASL2");
156+
assert(0);
157+
}
158+
159+
void conn_open_stream(xmpp_conn_t *conn)
160+
{
161+
(void)conn;
162+
puts("should not reset connection in SASL2");
163+
assert(0);
164+
}
165+
void send_raw_string(xmpp_conn_t *conn, const char *fmt, ...)
166+
{
167+
(void)conn;
168+
(void)fmt;
169+
}
170+
171+
#define strophe_warn(x, ...) (void)x
172+
#define strophe_debug(x, ...) (void)x
173+
174+
void strophe_error(const xmpp_ctx_t *ctx,
175+
const char *area,
176+
const char *fmt,
177+
...)
178+
{
179+
(void)ctx;
180+
(void)area;
181+
(void)fmt;
182+
}
183+
184+
void *strophe_alloc(const xmpp_ctx_t *ctx, size_t size)
185+
{
186+
(void)ctx;
187+
return malloc(size);
188+
}
189+
190+
void strophe_free(const xmpp_ctx_t *ctx, void *p)
191+
{
192+
(void)ctx;
193+
free(p);
194+
}
195+
196+
void *strophe_realloc(const xmpp_ctx_t *ctx, void *p, size_t size)
197+
{
198+
(void)ctx;
199+
return realloc(p, size);
200+
}
201+
202+
xmpp_conn_t *xmpp_conn_new(xmpp_ctx_t *ctx)
203+
{
204+
xmpp_conn_t *conn = malloc(sizeof(*conn));
205+
conn->ctx = ctx;
206+
return conn;
207+
}
208+
209+
int xmpp_conn_release(xmpp_conn_t *conn)
210+
{
211+
free(conn);
212+
return 0;
213+
}
214+
215+
/* include auth.c to access static functions */
216+
#include "src/auth.c"
217+
218+
/* If SASL2 isn't set, it shouldn't be used */
219+
static int test_make_sasl_auth()
220+
{
221+
xmpp_conn_t conn = {.sasl_support = SASL_MASK_PLAIN};
222+
xmpp_stanza_t *auth =
223+
_make_sasl_auth(&conn, "PLAIN", "AGZvb0BiYXIuY29tAHNlY3JldA==");
224+
225+
COMPARE(xmpp_stanza_get_name(auth), "auth");
226+
COMPARE(xmpp_stanza_get_ns(auth), XMPP_NS_SASL);
227+
COMPARE(xmpp_stanza_get_attribute(auth, "mechanism"), "PLAIN");
228+
229+
xmpp_stanza_release(auth);
230+
return 0;
231+
}
232+
233+
static int test_make_sasl_auth_v2()
234+
{
235+
xmpp_conn_t conn = {.sasl_support = SASL_MASK_SASL2 | SASL_MASK_PLAIN};
236+
xmpp_stanza_t *auth =
237+
_make_sasl_auth(&conn, "PLAIN", "AGZvb0BiYXIuY29tAHNlY3JldA==");
238+
xmpp_stanza_t *initial_response =
239+
xmpp_stanza_get_child_by_name(auth, "initial-response");
240+
241+
assert(initial_response != NULL);
242+
COMPARE(xmpp_stanza_get_name(auth), "authenticate");
243+
COMPARE(xmpp_stanza_get_ns(auth), XMPP_NS_SASL2);
244+
COMPARE(xmpp_stanza_get_attribute(auth, "mechanism"), "PLAIN");
245+
COMPARE(xmpp_stanza_get_ns(initial_response), XMPP_NS_SASL2);
246+
247+
xmpp_stanza_release(auth);
248+
return 0;
249+
}
250+
251+
static int test_scram_challenge_v2(xmpp_ctx_t *ctx)
252+
{
253+
extern const struct hash_alg scram_sha1;
254+
xmpp_conn_t conn = {.jid = "foo@bar.com",
255+
.pass = "secret",
256+
.sasl_support = SASL_MASK_SASL2 | SASL_MASK_SCRAMSHA1};
257+
struct scram_user_data scram_ctx = {.alg = &scram_sha1,
258+
.first_bare = "n=foo,r=random-nonce",
259+
.channel_binding =
260+
strophe_strdup(ctx, "biws")};
261+
struct scram_user_data *scram_ctx_heap = malloc(sizeof(*scram_ctx_heap));
262+
xmpp_stanza_t *stanza = xmpp_stanza_new(ctx);
263+
xmpp_stanza_t *tstanza = xmpp_stanza_new(ctx);
264+
265+
*scram_ctx_heap = scram_ctx;
266+
xmpp_stanza_set_name(stanza, "challenge");
267+
xmpp_stanza_set_ns(stanza, XMPP_NS_SASL2);
268+
xmpp_stanza_set_text(tstanza, "cj1meWtvK2QycGJiRmdITkRyOXBRdG16aHZ1U2EzeTg4"
269+
"dDBkcGNjOVU3LHM9UVNYQ1IrUTZz"
270+
"ZWs4YmY5MixpPTQwOTY=");
271+
xmpp_stanza_add_child(stanza, tstanza);
272+
xmpp_stanza_release(tstanza);
273+
274+
_handle_scram_challenge(&conn, stanza, scram_ctx_heap);
275+
276+
assert(last_sent_stanza != NULL);
277+
COMPARE(xmpp_stanza_get_name(last_sent_stanza), "response");
278+
COMPARE(xmpp_stanza_get_ns(last_sent_stanza), XMPP_NS_SASL2);
279+
COMPARE(xmpp_stanza_get_text(last_sent_stanza),
280+
"Yz1iaXdzLHI9ZnlrbytkMnBiYkZnSE5EcjlwUXRtemh2dVNhM3k4OHQwZHBjYzlVNy"
281+
"xwPTZCY2VjL3kyM1N1RlhkS1VucFpZTnRSRHJIQT0=");
282+
283+
xmpp_stanza_release(last_sent_stanza);
284+
last_sent_stanza = NULL;
285+
xmpp_stanza_release(stanza);
286+
287+
return 0;
288+
}
289+
290+
static int test_sasl_result_v2_success(xmpp_ctx_t *ctx)
291+
{
292+
xmpp_conn_t conn = {.sasl_support = SASL_MASK_SASL2};
293+
xmpp_stanza_t *stanza;
294+
295+
stanza = xmpp_stanza_new(ctx);
296+
xmpp_stanza_set_name(stanza, "success");
297+
xmpp_stanza_set_ns(stanza, XMPP_NS_SASL2);
298+
299+
_handle_sasl_result(&conn, stanza, "SCRAM-SHA-1");
300+
301+
/* If connection resets, the reset stub will assert failure */
302+
303+
xmpp_stanza_release(stanza);
304+
305+
return 0;
306+
}
307+
308+
int main()
309+
{
310+
int ret;
311+
312+
printf("testing _make_sasl_auth (SASL 1.0)... ");
313+
ret = test_make_sasl_auth_v1();
314+
if (ret) {
315+
printf("failed!\n");
316+
return ret;
317+
}
318+
printf("ok.\n");
319+
320+
printf("testing _make_sasl_auth (SASL 2.0)... ");
321+
ret = test_make_sasl_auth_v2();
322+
if (ret) {
323+
printf("failed!\n");
324+
return ret;
325+
}
326+
printf("ok.\n");
327+
328+
printf("testing _handle_scram_challenge (SASL 2.0)... ");
329+
ret = test_scram_challenge_v2(NULL);
330+
if (ret) {
331+
printf("failed!\n");
332+
return ret;
333+
}
334+
printf("ok.\n");
335+
336+
printf("testing _handle_sasl_result success (SASL 2.0)... ");
337+
ret = test_sasl_result_v2_success(NULL);
338+
if (ret) {
339+
printf("failed!\n");
340+
return ret;
341+
}
342+
printf("ok.\n");
343+
344+
return ret;
345+
}

0 commit comments

Comments
 (0)