39bc83f004cb33a22e888cc45ff36f9b698e50fa
[feed/telephony.git] / libs / pjproject / patches / 0100-allow_multiple_auth_headers.patch
1 commit 8e95490e37938f45d9d812905246036c3185b94f
2 Author: Riza Sulistyo <trengginas@users.noreply.github.com>
3 Date: Thu Mar 24 12:53:03 2022 +0700
4
5 Add compile time option to allow multiple Authorization header (#3010)
6
7 --- a/pjsip/include/pjsip/sip_config.h
8 +++ b/pjsip/include/pjsip/sip_config.h
9 @@ -1280,6 +1280,18 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
10 # define PJSIP_AUTH_CNONCE_USE_DIGITS_ONLY 1
11 #endif
12
13 +/**
14 + * Allow client to send multiple Authorization header when receiving multiple
15 + * WWW-Authenticate header fields. If this is disabled, the stack will send
16 + * Authorization header field containing credentials that match the
17 + * topmost header field.
18 + *
19 + * Default is 0
20 + */
21 +#ifndef PJSIP_AUTH_ALLOW_MULTIPLE_AUTH_HEADER
22 +# define PJSIP_AUTH_ALLOW_MULTIPLE_AUTH_HEADER 0
23 +#endif
24 +
25 /*****************************************************************************
26 * SIP Event framework and presence settings.
27 */
28 @@ -1458,6 +1470,11 @@ PJ_INLINE(pjsip_cfg_t*) pjsip_cfg(void)
29 # define PJSIP_INV_ACCEPT_UNKNOWN_BODY PJ_FALSE
30 #endif
31
32 +/**
33 + * Dump configuration to log with verbosity equal to info(3).
34 + */
35 +PJ_DECL(void) pjsip_dump_config(void);
36 +
37 PJ_END_DECL
38
39 /**
40 --- a/pjsip/src/pjsip/sip_auth_client.c
41 +++ b/pjsip/src/pjsip/sip_auth_client.c
42 @@ -1367,7 +1367,7 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reini
43 chal_cnt = 0;
44 auth_cnt = 0;
45 last_auth_err = PJSIP_EAUTHNOAUTH;
46 - while (hdr != &rdata->msg_info.msg->hdr && auth_cnt == 0) {
47 + while (hdr != &rdata->msg_info.msg->hdr) {
48 pjsip_cached_auth *cached_auth;
49 const pjsip_www_authenticate_hdr *hchal;
50 pjsip_authorization_hdr *hauth;
51 @@ -1431,6 +1431,11 @@ PJ_DEF(pj_status_t) pjsip_auth_clt_reini
52 /* Process next header. */
53 hdr = hdr->next;
54 auth_cnt++;
55 +
56 +#if defined(PJSIP_AUTH_ALLOW_MULTIPLE_AUTH_HEADER) && \
57 + PJSIP_AUTH_ALLOW_MULTIPLE_AUTH_HEADER==0
58 + break;
59 +#endif
60 }
61
62 /* Check if challenge is present */
63 --- a/pjsip/src/pjsip/sip_config.c
64 +++ b/pjsip/src/pjsip/sip_config.c
65 @@ -19,6 +19,9 @@
66 */
67
68 #include <pjsip/sip_config.h>
69 +#include <pj/log.h>
70 +
71 +static const char *id = "sip_config.c";
72
73 /* pjsip configuration instance, initialized with default values */
74 pjsip_cfg_t pjsip_sip_cfg_var =
75 @@ -65,6 +68,195 @@ pjsip_cfg_t pjsip_sip_cfg_var =
76 }
77 };
78
79 +PJ_DEF(void) pjsip_dump_config(void)
80 +{
81 + PJ_LOG(3, (id, "Dumping PJSIP configurations:"));
82 + PJ_LOG(3, (id, " PJSIP_MAX_DIALOG_COUNT : %d",
83 + PJSIP_MAX_DIALOG_COUNT));
84 + PJ_LOG(3, (id, " PJSIP_MAX_TRANSPORTS : %d",
85 + PJSIP_MAX_TRANSPORTS));
86 + PJ_LOG(3, (id, " PJSIP_TPMGR_HTABLE_SIZE : %d",
87 + PJSIP_TPMGR_HTABLE_SIZE));
88 + PJ_LOG(3, (id, " PJSIP_MAX_URL_SIZE : %d",
89 + PJSIP_MAX_URL_SIZE));
90 + PJ_LOG(3, (id, " PJSIP_MAX_MODULE : %d",
91 + PJSIP_MAX_MODULE));
92 + PJ_LOG(3, (id, " PJSIP_MAX_PKT_LEN : %d",
93 + PJSIP_MAX_PKT_LEN));
94 + PJ_LOG(3, (id, " PJSIP_HANDLE_EVENTS_HAS_SLEEP_ON_ERR : %d",
95 + PJSIP_HANDLE_EVENTS_HAS_SLEEP_ON_ERR));
96 + PJ_LOG(3, (id, " PJSIP_ACCEPT_MULTIPLE_SDP_ANSWERS : %d",
97 + PJSIP_ACCEPT_MULTIPLE_SDP_ANSWERS));
98 + PJ_LOG(3, (id, " PJSIP_UDP_SIZE_THRESHOLD : %d",
99 + PJSIP_UDP_SIZE_THRESHOLD));
100 + PJ_LOG(3, (id, " PJSIP_INCLUDE_ALLOW_HDR_IN_DLG : %d",
101 + PJSIP_INCLUDE_ALLOW_HDR_IN_DLG));
102 + PJ_LOG(3, (id, " PJSIP_SAFE_MODULE : %d",
103 + PJSIP_SAFE_MODULE));
104 + PJ_LOG(3, (id, " PJSIP_CHECK_VIA_SENT_BY : %d",
105 + PJSIP_CHECK_VIA_SENT_BY));
106 + PJ_LOG(3, (id, " PJSIP_UNESCAPE_IN_PLACE : %d",
107 + PJSIP_UNESCAPE_IN_PLACE));
108 + PJ_LOG(3, (id, " PJSIP_MAX_NET_EVENTS : %d",
109 + PJSIP_MAX_NET_EVENTS));
110 + PJ_LOG(3, (id, " PJSIP_MAX_TIMED_OUT_ENTRIES : %d",
111 + PJSIP_MAX_TIMED_OUT_ENTRIES));
112 + PJ_LOG(3, (id, " PJSIP_TRANSPORT_IDLE_TIME : %d",
113 + PJSIP_TRANSPORT_IDLE_TIME));
114 + PJ_LOG(3, (id, " PJSIP_TRANSPORT_SERVER_IDLE_TIME : %d",
115 + PJSIP_TRANSPORT_SERVER_IDLE_TIME));
116 + PJ_LOG(3, (id, " PJSIP_MAX_TRANSPORT_USAGE : %d",
117 + PJSIP_MAX_TRANSPORT_USAGE));
118 + PJ_LOG(3, (id, " PJSIP_TCP_TRANSPORT_BACKLOG : %d",
119 + PJSIP_TCP_TRANSPORT_BACKLOG));
120 + PJ_LOG(3, (id, " PJSIP_TCP_TRANSPORT_REUSEADDR : %d",
121 + PJSIP_TCP_TRANSPORT_REUSEADDR));
122 + PJ_LOG(3, (id, " PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER : %d",
123 + PJSIP_TCP_TRANSPORT_DONT_CREATE_LISTENER));
124 + PJ_LOG(3, (id, " PJSIP_TLS_TRANSPORT_DONT_CREATE_LISTENER : %d",
125 + PJSIP_TLS_TRANSPORT_DONT_CREATE_LISTENER));
126 + PJ_LOG(3, (id, " PJSIP_TCP_KEEP_ALIVE_INTERVAL : %d",
127 + PJSIP_TCP_KEEP_ALIVE_INTERVAL));
128 + PJ_LOG(3, (id, " PJSIP_POOL_INC_TRANSPORT : %d",
129 + PJSIP_POOL_INC_TRANSPORT));
130 + PJ_LOG(3, (id, " PJSIP_POOL_LEN_TDATA : %d",
131 + PJSIP_POOL_LEN_TDATA));
132 + PJ_LOG(3, (id, " PJSIP_POOL_INC_TDATA : %d",
133 + PJSIP_POOL_INC_TDATA));
134 + PJ_LOG(3, (id, " PJSIP_POOL_LEN_UA : %d",
135 + PJSIP_POOL_LEN_UA));
136 + PJ_LOG(3, (id, " PJSIP_POOL_INC_UA : %d",
137 + PJSIP_POOL_INC_UA));
138 + PJ_LOG(3, (id, " PJSIP_POOL_EVSUB_LEN : %d",
139 + PJSIP_POOL_EVSUB_LEN));
140 + PJ_LOG(3, (id, " PJSIP_POOL_EVSUB_INC : %d",
141 + PJSIP_POOL_EVSUB_INC));
142 + PJ_LOG(3, (id, " PJSIP_MAX_FORWARDS_VALUE : %d",
143 + PJSIP_MAX_FORWARDS_VALUE));
144 + PJ_LOG(3, (id, " PJSIP_RFC3261_BRANCH_ID : %s",
145 + PJSIP_RFC3261_BRANCH_ID));
146 + PJ_LOG(3, (id, " PJSIP_RFC3261_BRANCH_LEN : %d",
147 + PJSIP_RFC3261_BRANCH_LEN));
148 + PJ_LOG(3, (id, " PJSIP_POOL_TSX_LAYER_LEN : %d",
149 + PJSIP_POOL_TSX_LAYER_LEN));
150 + PJ_LOG(3, (id, " PJSIP_POOL_TSX_LAYER_INC : %d",
151 + PJSIP_POOL_TSX_LAYER_INC));
152 + PJ_LOG(3, (id, " PJSIP_POOL_TSX_LEN : %d",
153 + PJSIP_POOL_TSX_LEN));
154 + PJ_LOG(3, (id, " PJSIP_POOL_TSX_INC : %d",
155 + PJSIP_POOL_TSX_INC));
156 + PJ_LOG(3, (id, " PJSIP_TSX_1XX_RETRANS_DELAY : %d",
157 + PJSIP_TSX_1XX_RETRANS_DELAY));
158 + PJ_LOG(3, (id, " PJSIP_TSX_UAS_CONTINUE_ON_TP_ERROR : %d",
159 + PJSIP_TSX_UAS_CONTINUE_ON_TP_ERROR));
160 + PJ_LOG(3, (id, " PJSIP_MAX_TSX_KEY_LEN : %d",
161 + PJSIP_MAX_TSX_KEY_LEN));
162 + PJ_LOG(3, (id, " PJSIP_POOL_LEN_USER_AGENT : %d",
163 + PJSIP_POOL_LEN_USER_AGENT));
164 + PJ_LOG(3, (id, " PJSIP_POOL_INC_USER_AGENT : %d",
165 + PJSIP_POOL_INC_USER_AGENT));
166 + PJ_LOG(3, (id, " PJSIP_MAX_BRANCH_LEN : %d",
167 + PJSIP_MAX_HNAME_LEN));
168 + PJ_LOG(3, (id, " PJSIP_POOL_LEN_DIALOG : %d",
169 + PJSIP_POOL_LEN_DIALOG));
170 + PJ_LOG(3, (id, " PJSIP_POOL_INC_DIALOG : %d",
171 + PJSIP_POOL_INC_DIALOG));
172 + PJ_LOG(3, (id, " PJSIP_MAX_HEADER_TYPES : %d",
173 + PJSIP_MAX_HEADER_TYPES));
174 + PJ_LOG(3, (id, " PJSIP_MAX_URI_TYPES : %d",
175 + PJSIP_MAX_URI_TYPES));
176 + PJ_LOG(3, (id, " PJSIP_AUTH_HEADER_CACHING : %d",
177 + PJSIP_AUTH_HEADER_CACHING));
178 + PJ_LOG(3, (id, " PJSIP_AUTH_AUTO_SEND_NEXT : %d",
179 + PJSIP_AUTH_AUTO_SEND_NEXT));
180 + PJ_LOG(3, (id, " PJSIP_AUTH_QOP_SUPPORT : %d",
181 + PJSIP_AUTH_QOP_SUPPORT));
182 + PJ_LOG(3, (id, " PJSIP_MAX_STALE_COUNT : %d",
183 + PJSIP_MAX_STALE_COUNT));
184 + PJ_LOG(3, (id, " PJSIP_HAS_DIGEST_AKA_AUTH : %d",
185 + PJSIP_HAS_DIGEST_AKA_AUTH));
186 + PJ_LOG(3, (id, " PJSIP_REGISTER_CLIENT_DELAY_BEFORE_REFRESH : %d",
187 + PJSIP_REGISTER_CLIENT_DELAY_BEFORE_REFRESH));
188 + PJ_LOG(3, (id, " PJSIP_REGISTER_ALLOW_EXP_REFRESH : %d",
189 + PJSIP_REGISTER_ALLOW_EXP_REFRESH));
190 + PJ_LOG(3, (id, " PJSIP_AUTH_CACHED_POOL_MAX_SIZE : %d",
191 + PJSIP_AUTH_CACHED_POOL_MAX_SIZE));
192 + PJ_LOG(3, (id, " PJSIP_AUTH_CNONCE_USE_DIGITS_ONLY : %d",
193 + PJSIP_AUTH_CNONCE_USE_DIGITS_ONLY));
194 + PJ_LOG(3, (id, " PJSIP_AUTH_ALLOW_MULTIPLE_AUTH_HEADER : %d",
195 + PJSIP_AUTH_ALLOW_MULTIPLE_AUTH_HEADER));
196 + PJ_LOG(3, (id, " PJSIP_EVSUB_TIME_UAC_REFRESH : %d",
197 + PJSIP_EVSUB_TIME_UAC_REFRESH));
198 + PJ_LOG(3, (id, " PJSIP_PUBLISHC_DELAY_BEFORE_REFRESH : %d",
199 + PJSIP_PUBLISHC_DELAY_BEFORE_REFRESH));
200 + PJ_LOG(3, (id, " PJSIP_EVSUB_TIME_UAC_TERMINATE : %d",
201 + PJSIP_EVSUB_TIME_UAC_TERMINATE));
202 + PJ_LOG(3, (id, " PJSIP_EVSUB_TIME_UAC_WAIT_NOTIFY : %d",
203 + PJSIP_EVSUB_TIME_UAC_WAIT_NOTIFY));
204 + PJ_LOG(3, (id, " PJSIP_PRES_DEFAULT_EXPIRES : %d",
205 + PJSIP_PRES_DEFAULT_EXPIRES));
206 + PJ_LOG(3, (id, " PJSIP_PRES_BAD_CONTENT_RESPONSE : %d",
207 + PJSIP_PRES_BAD_CONTENT_RESPONSE));
208 + PJ_LOG(3, (id, " PJSIP_PRES_PIDF_ADD_TIMESTAMP : %d",
209 + PJSIP_PRES_PIDF_ADD_TIMESTAMP));
210 + PJ_LOG(3, (id, " PJSIP_SESS_TIMER_DEF_SE : %d",
211 + PJSIP_SESS_TIMER_DEF_SE));
212 + PJ_LOG(3, (id, " PJSIP_SESS_TIMER_RETRY_DELAY : %d",
213 + PJSIP_SESS_TIMER_RETRY_DELAY));
214 + PJ_LOG(3, (id, " PJSIP_PUBLISHC_QUEUE_REQUEST : %d",
215 + PJSIP_PUBLISHC_QUEUE_REQUEST));
216 + PJ_LOG(3, (id, " PJSIP_MWI_DEFAULT_EXPIRES : %d",
217 + PJSIP_MWI_DEFAULT_EXPIRES));
218 + PJ_LOG(3, (id, " PJSIP_HAS_TX_DATA_LIST : %d",
219 + PJSIP_HAS_TX_DATA_LIST));
220 + PJ_LOG(3, (id, " PJSIP_INV_ACCEPT_UNKNOWN_BODY : %d",
221 + PJSIP_INV_ACCEPT_UNKNOWN_BODY));
222 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.allow_port_in_fromto_hdr : %d",
223 + pjsip_cfg()->endpt.allow_port_in_fromto_hdr));
224 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.accept_replace_in_early_state : %d",
225 + pjsip_cfg()->endpt.accept_replace_in_early_state));
226 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.allow_tx_hash_in_uri : %d",
227 + pjsip_cfg()->endpt.allow_tx_hash_in_uri));
228 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.disable_rport : %d",
229 + pjsip_cfg()->endpt.disable_rport));
230 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.disable_tcp_switch : %d",
231 + pjsip_cfg()->endpt.disable_tcp_switch));
232 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.disable_tls_switch : %d",
233 + pjsip_cfg()->endpt.disable_tls_switch));
234 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.follow_early_media_fork : %d",
235 + pjsip_cfg()->endpt.follow_early_media_fork));
236 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.req_has_via_alias : %d",
237 + pjsip_cfg()->endpt.req_has_via_alias));
238 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.resolve_hostname_to_get_interface:%d",
239 + pjsip_cfg()->endpt.resolve_hostname_to_get_interface));
240 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.disable_secure_dlg_check : %d",
241 + pjsip_cfg()->endpt.disable_secure_dlg_check));
242 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.use_compact_form : %d",
243 + pjsip_cfg()->endpt.use_compact_form));
244 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.accept_multiple_sdp_answers : %d",
245 + pjsip_cfg()->endpt.accept_multiple_sdp_answers));
246 + PJ_LOG(3, (id, " pjsip_cfg()->endpt.keep_inv_after_tsx_timeout : %d",
247 + pjsip_cfg()->endpt.keep_inv_after_tsx_timeout));
248 + PJ_LOG(3, (id, " pjsip_cfg()->tsx.max_count : %d",
249 + pjsip_cfg()->tsx.max_count));
250 + PJ_LOG(3, (id, " pjsip_cfg()->tsx.t1 : %d",
251 + pjsip_cfg()->tsx.t1));
252 + PJ_LOG(3, (id, " pjsip_cfg()->tsx.t2 : %d",
253 + pjsip_cfg()->tsx.t2));
254 + PJ_LOG(3, (id, " pjsip_cfg()->tsx.t4 : %d",
255 + pjsip_cfg()->tsx.t4));
256 + PJ_LOG(3, (id, " pjsip_cfg()->td : %d",
257 + pjsip_cfg()->tsx.td));
258 + PJ_LOG(3, (id, " pjsip_cfg()->regc.check_contact : %d",
259 + pjsip_cfg()->regc.check_contact));
260 + PJ_LOG(3, (id, " pjsip_cfg()->regc.add_xuid_param : %d",
261 + pjsip_cfg()->regc.add_xuid_param));
262 + PJ_LOG(3, (id, " pjsip_cfg()->tcp.keep_alive_interval : %d",
263 + pjsip_cfg()->tcp.keep_alive_interval));
264 + PJ_LOG(3, (id, " pjsip_cfg()->tls.keep_alive_interval : %d",
265 + pjsip_cfg()->tls.keep_alive_interval));
266 +}
267 +
268
269 #ifdef PJ_DLL
270 PJ_DEF(pjsip_cfg_t*) pjsip_cfg(void)
271 --- a/pjsip/src/pjsua-lib/pjsua_core.c
272 +++ b/pjsip/src/pjsua-lib/pjsua_core.c
273 @@ -3443,8 +3443,10 @@ PJ_DEF(void) pjsua_dump(pj_bool_t detail
274 old_decor = pj_log_get_decor();
275 pj_log_set_decor(old_decor & (PJ_LOG_HAS_NEWLINE | PJ_LOG_HAS_CR));
276
277 - if (detail)
278 + if (detail) {
279 pj_dump_config();
280 + pjsip_dump_config();
281 + }
282
283 pjsip_endpt_dump(pjsua_get_pjsip_endpt(), detail);
284
285 --- a/tests/pjsua/inc_sip.py
286 +++ b/tests/pjsua/inc_sip.py
287 @@ -306,9 +306,11 @@ class RecvfromTransaction:
288 body = None
289 # Pattern to be expected on pjsua when receiving the response
290 expect = ""
291 + # Required config
292 + pj_config = ""
293
294 def __init__(self, title, resp_code, check_cseq=True,
295 - include=[], exclude=[], cmds=[], resp_hdr=[], resp_body=None, expect=""):
296 + include=[], exclude=[], cmds=[], resp_hdr=[], resp_body=None, expect="", pj_config=""):
297 self.title = title
298 self.cmds = cmds
299 self.include = include
300 @@ -317,6 +319,7 @@ class RecvfromTransaction:
301 self.resp_hdr = resp_hdr
302 self.body = resp_body
303 self.expect = expect
304 + self.pj_config=pj_config
305
306
307 class RecvfromCfg:
308 @@ -328,15 +331,18 @@ class RecvfromCfg:
309 transaction = None
310 # Use TCP?
311 tcp = False
312 + # Required config
313 + pj_config = ""
314
315 # Note:
316 # Any "$PORT" string in the pjsua_args will be replaced
317 # by server port
318 - def __init__(self, name, pjsua_args, transaction, tcp=False):
319 + def __init__(self, name, pjsua_args, transaction, tcp=False, pj_config=""):
320 self.name = name
321 self.inst_param = cfg.InstanceParam("pjsua", pjsua_args)
322 self.transaction = transaction
323 self.tcp=tcp
324 + self.pj_config=pj_config
325
326
327
328 --- a/tests/pjsua/mod_recvfrom.py
329 +++ b/tests/pjsua/mod_recvfrom.py
330 @@ -18,10 +18,20 @@ def test_func(test):
331 local_port=srv_port,
332 tcp=cfg_file.recvfrom_cfg.tcp)
333
334 + config = pjsua.get_config(cfg_file.recvfrom_cfg.pj_config)
335 + print "Config : " + config
336 +
337 last_cseq = 0
338 last_method = ""
339 last_call_id = ""
340 for t in cfg_file.recvfrom_cfg.transaction:
341 + # Check if transaction requires configuration
342 + if t.pj_config != "":
343 + r = re.compile(t.pj_config, re.I)
344 + if r.search(config) == None:
345 + print "Configuration : " + t.pj_config + " not found, skipping"
346 + continue
347 +
348 # Print transaction title
349 if t.title != "":
350 dlg.trace(t.title)
351 --- a/tests/pjsua/run.py
352 +++ b/tests/pjsua/run.py
353 @@ -249,6 +249,10 @@ class Expect(threading.Thread):
354 time.sleep(0.01)
355 return None
356
357 + def get_config(self, key_config):
358 + self.send("dd")
359 + line = self.expect(key_config);
360 + return line
361
362 def sync_stdout(self):
363 if not self.use_telnet:
364 --- a/tests/pjsua/scripts-recvfrom/215_reg_good_multi_ok.py
365 +++ b/tests/pjsua/scripts-recvfrom/215_reg_good_multi_ok.py
366 @@ -14,16 +14,27 @@ req1 = sip.RecvfromTransaction("Initial
367 expect="SIP/2.0 401"
368 )
369
370 -req2 = sip.RecvfromTransaction("Registration retry with auth", 200,
371 +req2 = sip.RecvfromTransaction("Registration retry with auth (not allowed multiple auth)", 200,
372 include=["REGISTER sip",
373 - # Must only have 1 Auth hdr since #2887
374 "Authorization:", # [\\s\\S]+Authorization:"
375 "realm=\"python1\"", # "realm=\"python2\"",
376 "username=\"theuser1\"", # "username=\"theuser2\"",
377 "nonce=\"1234\"", # "nonce=\"6789\"",
378 "response="],
379 - expect="registration success"
380 + expect="registration success",
381 + pj_config="PJSIP_AUTH_ALLOW_MULTIPLE_AUTH_HEADER.*: 0"
382 )
383
384 +req3 = sip.RecvfromTransaction("Registration retry with auth (allowed multiple auth)", 200,
385 + include=["REGISTER sip",
386 + "Authorization:[\\s\\S]+Authorization:", # Must have 2 Auth hdrs
387 + "realm=\"python1\"", "realm=\"python2\"",
388 + "username=\"theuser1\"", "username=\"theuser2\"",
389 + "nonce=\"1234\"", "nonce=\"6789\"",
390 + "response="],
391 + expect="registration success",
392 + pj_config="PJSIP_AUTH_ALLOW_MULTIPLE_AUTH_HEADER.*: 1"
393 + )
394 +
395 recvfrom_cfg = sip.RecvfromCfg("Multiple authentication challenges",
396 - pjsua, [req1, req2])
397 + pjsua, [req1, req2, req3], pj_config="PJSIP_AUTH_ALLOW_MULTIPLE_AUTH_HEADER")