Release 1.25.0 -- Buddy Idle Time, RTF
[siplcs.git] / src / core / sip-sec-digest-tests.c
blob5c219ab8e327f52c1a5dbc387d1a7b5928425786
1 /**
2 * @file sip-sec-digest-test.c
4 * pidgin-sipe
6 * Copyright (C) 2013-2019 SIPE Project <http://sipe.sourceforge.net/>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <stdint.h>
29 #include <glib.h>
31 #include "sip-transport.h"
32 #include "sipe-common.h"
33 #include "sipe-crypt.h"
34 #include "uuid.h"
36 #define SIP_SEC_DIGEST_COMPILING_TEST
37 static const gchar *cnonce_fixed;
38 #include "sip-sec-digest.c"
41 * Stubs
43 gboolean sipe_backend_debug_enabled(void)
45 return(TRUE);
48 void sipe_backend_debug_literal(sipe_debug_level level,
49 const gchar *msg)
51 printf("DEBUG(%d): %s\n", level, msg);
54 void sipe_backend_debug(sipe_debug_level level,
55 const gchar *format,
56 ...)
58 va_list ap;
59 gchar *newformat = g_strdup_printf("DEBUG(%d): %s\n", level, format);
61 va_start(ap, format);
62 vprintf(newformat, ap);
63 va_end(ap);
65 g_free(newformat);
68 const gchar *sip_transport_epid(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private)
70 return(NULL);
73 const gchar *sip_transport_ip_address(SIPE_UNUSED_PARAMETER struct sipe_core_private *sipe_private)
75 return(NULL);
78 char *generateUUIDfromEPID(SIPE_UNUSED_PARAMETER const gchar *epid)
80 return(NULL);
83 char *sipe_get_epid(SIPE_UNUSED_PARAMETER const char *self_sip_uri,
84 SIPE_UNUSED_PARAMETER const char *hostname,
85 SIPE_UNUSED_PARAMETER const char *ip_address)
87 return(NULL);
90 /* needed when linking against NSS */
91 void md4sum(const uint8_t *data, uint32_t length, uint8_t *digest);
92 void md4sum(SIPE_UNUSED_PARAMETER const uint8_t *data,
93 SIPE_UNUSED_PARAMETER uint32_t length,
94 SIPE_UNUSED_PARAMETER uint8_t *digest)
99 * Tester code
101 #define PARSED_USERNAME 0
102 #define PARSED_REALM 1
103 #define PARSED_NONCE 2
104 #define PARSED_URI 3
105 #define PARSED_QOP 4
106 #define PARSED_NC 5
107 #define PARSED_CNONCE 6
108 #define PARSED_RESPONSE 7
109 #define PARSED_OPAQUE 8
110 #define PARSED_MAX 9
111 static void parse(const gchar *string,
112 gchar *parsed[PARSED_MAX])
114 const gchar *header;
115 const gchar *param;
116 guint i;
118 for (i = 0; i < PARSED_MAX; i++)
119 parsed[i] = NULL;
121 if (strstr(string, "Digest ") == NULL)
122 return;
123 header = string + 7;
125 /* skip white space */
126 while (*header == ' ')
127 header++;
129 /* start of next parameter value */
130 while ((param = strchr(header, '=')) != NULL) {
131 const gchar *end;
133 /* parameter value type */
134 param++;
135 if (*param == '"') {
136 /* string: xyz="..."(,) */
137 end = strchr(++param, '"');
138 if (!end) {
139 SIPE_DEBUG_ERROR("parse: corrupted string parameter near '%s'", header);
140 break;
142 } else {
143 /* number: xyz=12345(,) */
144 end = strchr(param, ',');
145 if (!end) {
146 /* last parameter */
147 end = param + strlen(param);
151 #define COMPARE(string, index) \
152 if (g_str_has_prefix(header, #string "=")) { \
153 g_free(parsed[ PARSED_ ## index]); \
154 parsed[ PARSED_ ## index] = g_strndup(param, end - param); \
155 } else
157 COMPARE(username, USERNAME)
158 COMPARE(realm, REALM)
159 COMPARE(nonce, NONCE)
160 COMPARE(uri, URI)
161 COMPARE(qop, QOP)
162 COMPARE(nc, NC)
163 COMPARE(cnonce, CNONCE)
164 COMPARE(response, RESPONSE)
165 COMPARE(opaque, OPAQUE)
166 { /* ignore */ }
168 /* skip to next parameter */
169 while ((*end == '"') || (*end == ',') || (*end == ' '))
170 end++;
171 header = end;
175 static guint expected(const gchar *reference,
176 const gchar *testvalue)
178 gchar *reference_parsed[PARSED_MAX];
179 gchar *testvalue_parsed[PARSED_MAX];
180 guint i;
181 guint failed = 0;
183 parse(reference, reference_parsed);
184 parse(testvalue, testvalue_parsed);
185 for (i = 0; i < PARSED_MAX; i++) {
186 gchar *ref = reference_parsed[i];
187 gchar *test = testvalue_parsed[i];
188 if (!sipe_strequal(ref, test) && (ref || test)) {
189 SIPE_DEBUG_ERROR("FAILED(%d): expected '%s' got '%s'",
190 i, ref, test);
191 failed = 1;
193 g_free(test);
194 g_free(ref);
196 SIPE_DEBUG_INFO("Response: %s", testvalue);
198 return(failed);
201 int main(SIPE_UNUSED_PARAMETER int argc, SIPE_UNUSED_PARAMETER char *argv[])
203 guint failed = 0;
205 /* Initialization for crypto backend (test mode) */
206 sipe_crypto_init(FALSE);
208 #define RUNTEST(_user, _password, _cnonce, _header, _method, _uri, _reference) \
210 struct sipe_core_private sipe_private; \
211 gchar *response; \
212 printf("\n"); \
213 sipe_private.authuser = _user ; \
214 sipe_private.password = _password ; \
215 cnonce_fixed = _cnonce; \
216 response = sip_sec_digest_authorization(&sipe_private, _header, _method, _uri); \
217 failed += expected(_reference, response); \
218 g_free(response); \
222 * RFC-2617 Section 3.5
224 RUNTEST("Mufasa", "Circle Of Life", "0a4f113b",
225 "realm=\"testrealm@host.com\", qop=\"auth,auth-int\", nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"",
226 "GET",
227 "/dir/index.html",
228 "Digest username=\"Mufasa\", realm=\"testrealm@host.com\", nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", uri=\"/dir/index.html\", qop=auth, nc=00000001, cnonce=\"0a4f113b\", response=\"6629fae49393a05397450978507c4ef1\", opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"");
231 * http://www.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Authentication.html
233 RUNTEST("bob", "bob", "1672b410efa182c061c2f0a58acaa17d",
235 * The Server challenge shown does not correspond to the
236 * Client response. Use realm/nonce from the Client response.
238 * "realm=\"Members only\", nonce=\"LHOKe1l2BAA=5c373ae0d933a0bb6321125a56a2fcdb6fd7c93b\", algorithm=MD5, qop=\"auth\"",
240 "realm=\"members only\", nonce=\"5UImQA==3d76b2ab859e1770ec60ed285ec68a3e63028461\", algorithm=MD5, qop=\"auth\"",
241 "GET",
242 "/digest_auth/test.html",
243 "Digest username=\"bob\", realm=\"members only\", qop=\"auth\", algorithm=\"MD5\", uri=\"/digest_auth/test.html\", nonce=\"5UImQA==3d76b2ab859e1770ec60ed285ec68a3e63028461\", nc=00000001, cnonce=\"1672b410efa182c061c2f0a58acaa17d\", response=\"3d9ebe6b9534a7135a3fde59a5a72668\"");
245 return(failed);
249 Local Variables:
250 mode: c
251 c-file-style: "bsd"
252 indent-tabs-mode: t
253 tab-width: 8
254 End: