2 * @file sip-sec-digest-test.c
6 * Copyright (C) 2013-2016 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
30 #include "sip-transport.h"
31 #include "sipe-common.h"
32 #include "sipe-crypt.h"
35 #define SIP_SEC_DIGEST_COMPILING_TEST
36 static const gchar
*cnonce_fixed
;
37 #include "sip-sec-digest.c"
42 gboolean
sipe_backend_debug_enabled(void)
47 void sipe_backend_debug_literal(sipe_debug_level level
,
50 printf("DEBUG(%d): %s\n", level
, msg
);
53 void sipe_backend_debug(sipe_debug_level level
,
58 gchar
*newformat
= g_strdup_printf("DEBUG(%d): %s\n", level
, format
);
61 vprintf(newformat
, ap
);
67 const gchar
*sip_transport_epid(SIPE_UNUSED_PARAMETER
struct sipe_core_private
*sipe_private
)
72 const gchar
*sip_transport_ip_address(SIPE_UNUSED_PARAMETER
struct sipe_core_private
*sipe_private
)
77 char *generateUUIDfromEPID(SIPE_UNUSED_PARAMETER
const gchar
*epid
)
82 char *sipe_get_epid(SIPE_UNUSED_PARAMETER
const char *self_sip_uri
,
83 SIPE_UNUSED_PARAMETER
const char *hostname
,
84 SIPE_UNUSED_PARAMETER
const char *ip_address
)
89 /* needed when linking against NSS */
90 void md4sum(const guchar
*data
, gsize length
, guchar
*digest
);
91 void md4sum(SIPE_UNUSED_PARAMETER
const guchar
*data
,
92 SIPE_UNUSED_PARAMETER gsize length
,
93 SIPE_UNUSED_PARAMETER guchar
*digest
)
100 #define PARSED_USERNAME 0
101 #define PARSED_REALM 1
102 #define PARSED_NONCE 2
106 #define PARSED_CNONCE 6
107 #define PARSED_RESPONSE 7
108 #define PARSED_OPAQUE 8
110 static void parse(const gchar
*string
,
111 gchar
*parsed
[PARSED_MAX
])
117 for (i
= 0; i
< PARSED_MAX
; i
++)
120 if (strstr(string
, "Digest ") == NULL
)
124 /* skip white space */
125 while (*header
== ' ')
128 /* start of next parameter value */
129 while ((param
= strchr(header
, '=')) != NULL
) {
132 /* parameter value type */
135 /* string: xyz="..."(,) */
136 end
= strchr(++param
, '"');
138 SIPE_DEBUG_ERROR("parse: corrupted string parameter near '%s'", header
);
142 /* number: xyz=12345(,) */
143 end
= strchr(param
, ',');
146 end
= param
+ strlen(param
);
150 #define COMPARE(string, index) \
151 if (g_str_has_prefix(header, #string "=")) { \
152 g_free(parsed[ PARSED_ ## index]); \
153 parsed[ PARSED_ ## index] = g_strndup(param, end - param); \
156 COMPARE(username
, USERNAME
)
157 COMPARE(realm
, REALM
)
158 COMPARE(nonce
, NONCE
)
162 COMPARE(cnonce
, CNONCE
)
163 COMPARE(response
, RESPONSE
)
164 COMPARE(opaque
, OPAQUE
)
167 /* skip to next parameter */
168 while ((*end
== '"') || (*end
== ',') || (*end
== ' '))
174 static guint
expected(const gchar
*reference
,
175 const gchar
*testvalue
)
177 gchar
*reference_parsed
[PARSED_MAX
];
178 gchar
*testvalue_parsed
[PARSED_MAX
];
182 parse(reference
, reference_parsed
);
183 parse(testvalue
, testvalue_parsed
);
184 for (i
= 0; i
< PARSED_MAX
; i
++) {
185 gchar
*ref
= reference_parsed
[i
];
186 gchar
*test
= testvalue_parsed
[i
];
187 if (!sipe_strequal(ref
, test
) && (ref
|| test
)) {
188 SIPE_DEBUG_ERROR("FAILED(%d): expected '%s' got '%s'",
195 SIPE_DEBUG_INFO("Response: %s", testvalue
);
200 int main(SIPE_UNUSED_PARAMETER
int argc
, SIPE_UNUSED_PARAMETER
char *argv
[])
204 /* Initialization for crypto backend (test mode) */
205 sipe_crypto_init(FALSE
);
207 #define RUNTEST(_user, _password, _cnonce, _header, _method, _uri, _reference) \
209 struct sipe_core_private sipe_private; \
212 sipe_private.authuser = _user ; \
213 sipe_private.password = _password ; \
214 cnonce_fixed = _cnonce; \
215 response = sip_sec_digest_authorization(&sipe_private, _header, _method, _uri); \
216 failed += expected(_reference, response); \
221 * RFC-2617 Section 3.5
223 RUNTEST("Mufasa", "Circle Of Life", "0a4f113b",
224 "realm=\"testrealm@host.com\", qop=\"auth,auth-int\", nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"",
227 "Digest username=\"Mufasa\", realm=\"testrealm@host.com\", nonce=\"dcd98b7102dd2f0e8b11d0f600bfb0c093\", uri=\"/dir/index.html\", qop=auth, nc=00000001, cnonce=\"0a4f113b\", response=\"6629fae49393a05397450978507c4ef1\", opaque=\"5ccc069c403ebaf9f0171e9517f40e41\"");
230 * http://www.ntu.edu.sg/home/ehchua/programming/webprogramming/HTTP_Authentication.html
232 RUNTEST("bob", "bob", "1672b410efa182c061c2f0a58acaa17d",
234 * The Server challenge shown does not correspond to the
235 * Client response. Use realm/nonce from the Client response.
237 * "realm=\"Members only\", nonce=\"LHOKe1l2BAA=5c373ae0d933a0bb6321125a56a2fcdb6fd7c93b\", algorithm=MD5, qop=\"auth\"",
239 "realm=\"members only\", nonce=\"5UImQA==3d76b2ab859e1770ec60ed285ec68a3e63028461\", algorithm=MD5, qop=\"auth\"",
241 "/digest_auth/test.html",
242 "Digest username=\"bob\", realm=\"members only\", qop=\"auth\", algorithm=\"MD5\", uri=\"/digest_auth/test.html\", nonce=\"5UImQA==3d76b2ab859e1770ec60ed285ec68a3e63028461\", nc=00000001, cnonce=\"1672b410efa182c061c2f0a58acaa17d\", response=\"3d9ebe6b9534a7135a3fde59a5a72668\"");