belle_sip_register_tester.c 45.5 KB
Newer Older
Simon Morlat's avatar
Simon Morlat committed
1 2
/*
	belle-sip - SIP (RFC3261) library.
3
	Copyright (C) 2010  Belledonne Communications SARL
Simon Morlat's avatar
Simon Morlat committed
4

5 6 7 8
	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.
Simon Morlat's avatar
Simon Morlat committed
9

10 11 12 13
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
Simon Morlat's avatar
Simon Morlat committed
14

15 16
	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
Simon Morlat's avatar
Simon Morlat committed
17 18 19
*/

#include "belle-sip/belle-sip.h"
20
#include "belle_sip_internal.h"
Ghislain MARY's avatar
Ghislain MARY committed
21
#include "belle_sip_tester.h"
22

Simon Morlat's avatar
Simon Morlat committed
23 24
#include "register_tester.h"

Ghislain MARY's avatar
Ghislain MARY committed
25

26
const char *test_domain="sip2.linphone.org";
27
const char *auth_domain="sip.linphone.org";
jehan's avatar
jehan committed
28
const char *client_auth_domain="client.example.org";
Simon Morlat's avatar
Simon Morlat committed
29
const char *client_auth_outbound_proxy="sips:sip2.linphone.org:5063";
30
const char *no_server_running_here="sip:test.linphone.org:3;transport=tcp";
31
const char *no_response_here="sip:78.220.48.77:3;transport=%s";
32
const char *test_domain_tls_to_tcp="sip:sip2.linphone.org:5060;transport=tls";
33
const char *test_http_proxy_addr="sip.linphone.org";
34
const char *test_with_wrong_cname="sips:rototo.com;maddr=91.121.209.194";
35
int test_http_proxy_port = 3128 ;
jehan's avatar
jehan committed
36

jehan's avatar
jehan committed
37
static int is_register_ok;
38
static int number_of_challenge;
39
static int using_transaction;
40 41
static int io_error_count=0;

jehan's avatar
jehan committed
42 43 44
belle_sip_stack_t * stack;
belle_sip_provider_t *prov;
static belle_sip_listener_t* l;
Ghislain MARY's avatar
Ghislain MARY committed
45 46 47 48
belle_sip_request_t* authorized_request;
belle_sip_listener_callbacks_t listener_callbacks;
belle_sip_listener_t *listener;

49
static void process_dialog_terminated(void *user_ctx, const belle_sip_dialog_terminated_event_t *event){
50 51
	BELLESIP_UNUSED(user_ctx);
	BELLESIP_UNUSED(event);
52 53
	belle_sip_message("process_dialog_terminated called");
}
Ghislain MARY's avatar
Ghislain MARY committed
54

55
static void process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
56 57
	BELLESIP_UNUSED(user_ctx);
	BELLESIP_UNUSED(event);
58
	belle_sip_message("process_io_error, exiting main loop");
59
	belle_sip_main_loop_quit(belle_sip_stack_get_main_loop(stack));
60
	io_error_count++;
61
	/*BC_ASSERT(CU_FALSE);*/
62
}
Ghislain MARY's avatar
Ghislain MARY committed
63

64
static void process_request_event(void *user_ctx, const belle_sip_request_event_t *event){
65 66
	BELLESIP_UNUSED(user_ctx);
	BELLESIP_UNUSED(event);
67 68
	belle_sip_message("process_request_event");
}
Ghislain MARY's avatar
Ghislain MARY committed
69

70
static void process_response_event(void *user_ctx, const belle_sip_response_event_t *event){
71 72
	int status;
	belle_sip_request_t* request;
73
	BELLESIP_UNUSED(user_ctx);
74 75 76
	if (!BC_ASSERT_PTR_NOT_NULL(belle_sip_response_event_get_response(event))) {
		return;
	}
77 78 79
	belle_sip_message("process_response_event [%i] [%s]"
					,status=belle_sip_response_get_status_code(belle_sip_response_event_get_response(event))
					,belle_sip_response_get_reason_phrase(belle_sip_response_event_get_response(event)));
80 81 82


	if (status==401){
83 84
		belle_sip_header_cseq_t* cseq;
		belle_sip_client_transaction_t *t;
85
		belle_sip_uri_t *dest;
86 87
		// BC_ASSERT_NOT_EQUAL(number_of_challenge,2);
		BC_ASSERT_PTR_NOT_NULL(belle_sip_response_event_get_client_transaction(event)); /*require transaction mode*/
88
		dest=belle_sip_client_transaction_get_route(belle_sip_response_event_get_client_transaction(event));
89
		request=belle_sip_transaction_get_request(BELLE_SIP_TRANSACTION(belle_sip_response_event_get_client_transaction(event)));
90
		cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_CSEQ);
91
		belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+1);
92 93
		belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_AUTHORIZATION);
		belle_sip_message_remove_header(BELLE_SIP_MESSAGE(request),BELLE_SIP_PROXY_AUTHORIZATION);
94
		BC_ASSERT_TRUE(belle_sip_provider_add_authorization(prov,request,belle_sip_response_event_get_response(event),NULL,NULL,auth_domain));
95

96
		t=belle_sip_provider_create_client_transaction(prov,request);
97
		belle_sip_client_transaction_send_request_to(t,dest);
98
		number_of_challenge++;
99
		authorized_request=request;
100
		belle_sip_object_ref(authorized_request);
101
	}  else {
102
		BC_ASSERT_EQUAL(status,200,int,"%d");
103 104 105 106
		is_register_ok=1;
		using_transaction=belle_sip_response_event_get_client_transaction(event)!=NULL;
		belle_sip_main_loop_quit(belle_sip_stack_get_main_loop(stack));
	}
107
}
Ghislain MARY's avatar
Ghislain MARY committed
108

109
static void process_timeout(void *user_ctx, const belle_sip_timeout_event_t *event){
110 111
	BELLESIP_UNUSED(user_ctx);
	BELLESIP_UNUSED(event);
112 113
	belle_sip_message("process_timeout");
}
Ghislain MARY's avatar
Ghislain MARY committed
114

115
static void process_transaction_terminated(void *user_ctx, const belle_sip_transaction_terminated_event_t *event){
116 117
	BELLESIP_UNUSED(user_ctx);
	BELLESIP_UNUSED(event);
118 119
	belle_sip_message("process_transaction_terminated");
}
Ghislain MARY's avatar
Ghislain MARY committed
120

Simon Morlat's avatar
Simon Morlat committed
121
const char* belle_sip_tester_client_cert = /*for URI:sip:tester@client.example.org*/
jehan's avatar
jehan committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
		"-----BEGIN CERTIFICATE-----\n"
		"MIIDYzCCAsygAwIBAgIBCDANBgkqhkiG9w0BAQUFADCBuzELMAkGA1UEBhMCRlIx\n"
		"EzARBgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAcMCEdyZW5vYmxlMSIwIAYDVQQK\n"
		"DBlCZWxsZWRvbm5lIENvbW11bmljYXRpb25zMQwwCgYDVQQLDANMQUIxFjAUBgNV\n"
		"BAMMDUplaGFuIE1vbm5pZXIxOjA4BgkqhkiG9w0BCQEWK2plaGFuLm1vbm5pZXJA\n"
		"YmVsbGVkb25uZS1jb21tdW5pY2F0aW9ucy5jb20wHhcNMTMxMDAzMTQ0MTEwWhcN\n"
		"MjMxMDAxMTQ0MTEwWjCBtTELMAkGA1UEBhMCRlIxDzANBgNVBAgMBkZyYW5jZTER\n"
		"MA8GA1UEBwwIR3Jlbm9ibGUxIjAgBgNVBAoMGUJlbGxlZG9ubmUgQ29tbXVuaWNh\n"
		"dGlvbnMxDDAKBgNVBAsMA0xBQjEUMBIGA1UEAwwLY2xpZW50IGNlcnQxOjA4Bgkq\n"
		"hkiG9w0BCQEWK2plaGFuLm1vbm5pZXJAYmVsbGVkb25uZS1jb21tdW5pY2F0aW9u\n"
		"cy5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALZxC/qBi/zB/4lgI7V7\n"
		"I5TsmMmOp0+R/TCyVnYvKQuaJXh9i+CobVM7wj/pQg8RgsY1x+4mVwH1QbhOdIN0\n"
		"ExYHKgLTPlo9FaN6oHPOcHxU/wt552aZhCHC+ushwUUyjy8+T09UOP+xK9V7y5uD\n"
		"ZY+vIOvi6QNwc5cqyy8TREwNAgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4\n"
		"QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTL\n"
		"eWEg7jewRbQbKXSdBvsyygGIFzAfBgNVHSMEGDAWgBQGX13HFq9i+C1ucQOIoNYd\n"
		"KwR/ujANBgkqhkiG9w0BAQUFAAOBgQBTbEoi94pVfevbK22Oj8PJFsuy+el1pJG+\n"
		"h0XGM9SQGfbcS7PsV/MhFXtmpnmj3vQB3u5QtMGtWcLA2uxXi79i82gw+oEpBKHR\n"
		"sLqsNCzWNCL9n1pjpNSdqqBFGUdB9pSpnYalujAbuzkqq1ZLyzsElvK7pCaLQcSs\n"
		"oEncRDdPOA==\n"
		"-----END CERTIFICATE-----";

144 145 146
/* fingerprint of certificate generated using openssl x509 -fingerprint */
const char* belle_sip_tester_client_cert_fingerprint =
		"SHA-1 79:2F:9E:8B:28:CC:38:53:90:1D:71:DC:8F:70:66:75:E5:34:CE:C4";
jehan's avatar
jehan committed
147

Simon Morlat's avatar
Simon Morlat committed
148
const char* belle_sip_tester_private_key =
jehan's avatar
jehan committed
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
		"-----BEGIN ENCRYPTED PRIVATE KEY-----\n"
		"MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIbEHnQwhgRwoCAggA\n"
		"MBQGCCqGSIb3DQMHBAgmrtCEBCP9kASCAoCq9EKInROalaBSLWY44U4RVAC+CKdx\n"
		"Q8ooT7Bz/grgZuCiaGf0UKINJeV4LYHoP+AWjCH8EeebIA8dldNy5rGcBTt7sXd1\n"
		"QOGmnkBplXTW/NTsb9maYRK56kNJhLE4DR5X5keziV1Tdy2KBmTlpllsCXWsSOBq\n"
		"iI63PTaakIvZxA0TEmie5QQWpH777e/LmW3vVHdH8hhp2zeDDjfSW2E290+ce4Yj\n"
		"SDW9oFXvauzhzhSYRkUdfoJSbpu5MYwyzhjAXQpmBJDauu7+jAU/rQw6TLmYjDNZ\n"
		"3PYHzyD4N7tCG9u4mPBo33dhUirP+8E1BftHB+i/VIn6pI3ypMyiFZ1ZCHqi4vhW\n"
		"z7aChRrUY/8XWCpln3azcfj4SW+Mz62sAChY8rn+yyxFgIno8d9rrx67jyAnYJ6Q\n"
		"sfIMwKp3Sz5oI7IDk8If5SuBVkpqlRV+eZFT6zRRFk65beYpq70BN2mYaKzSV8A7\n"
		"rnciho/dfa9wvyWmkqXciBgWh18UTACOM9HPLmQef3FGaUDLiTAGS1osyypGUEPt\n"
		"Ox3u51qpYkibwyQZo1+ujQkh9PiKfevIAXmty0nTFWMEED15G2SJKjunw5N1rEAh\n"
		"M9jlYpLnATcfigPfGo19QrIPQ1c0LB4BqdwAWN3ZLe0QqYdgwzdcwIoLQRp9iDcw\n"
		"Omc31+38cTc2yGQ2Y2XHZkL8GY/rkqkbhVt9Rnh+VJxFeB6FlsL66EycApe07ngx\n"
		"QimGP57yp4aBzpJyW+6GPf8A/Ogsv3ay1QBLUiGEJtUglRHnl9F6nm5Nxm7wubVx\n"
		"WEuSefVM4xgB+mfQauAJu2N9yKhzXOytslZflpa06qJedlLYFk9njvcv\n"
		"-----END ENCRYPTED PRIVATE KEY-----\n";

Simon Morlat's avatar
Simon Morlat committed
167
const char* belle_sip_tester_private_key_passwd="secret";
jehan's avatar
jehan committed
168 169


170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
const char *belle_sip_tester_root_ca = 
"-----BEGIN CERTIFICATE-----\n"
"MIIDRjCCAq+gAwIBAgIJAJ3nFcA7qFrOMA0GCSqGSIb3DQEBBQUAMIG7MQswCQYD\n"
"VQQGEwJGUjETMBEGA1UECAwKU29tZS1TdGF0ZTERMA8GA1UEBwwIR3Jlbm9ibGUx\n"
"IjAgBgNVBAoMGUJlbGxlZG9ubmUgQ29tbXVuaWNhdGlvbnMxDDAKBgNVBAsMA0xB\n"
"QjEWMBQGA1UEAwwNSmVoYW4gTW9ubmllcjE6MDgGCSqGSIb3DQEJARYramVoYW4u\n"
"bW9ubmllckBiZWxsZWRvbm5lLWNvbW11bmljYXRpb25zLmNvbTAeFw0xMzA0MzAx\n"
"MzMwMThaFw0yMzA0MjgxMzMwMThaMIG7MQswCQYDVQQGEwJGUjETMBEGA1UECAwK\n"
"U29tZS1TdGF0ZTERMA8GA1UEBwwIR3Jlbm9ibGUxIjAgBgNVBAoMGUJlbGxlZG9u\n"
"bmUgQ29tbXVuaWNhdGlvbnMxDDAKBgNVBAsMA0xBQjEWMBQGA1UEAwwNSmVoYW4g\n"
"TW9ubmllcjE6MDgGCSqGSIb3DQEJARYramVoYW4ubW9ubmllckBiZWxsZWRvbm5l\n"
"LWNvbW11bmljYXRpb25zLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n"
"z5F8mMh3SUr6NUd7tq2uW2Kdn22Zn3kNpLYb78AQK4IoQMOLGXbBdyoXvz1fublg\n"
"bxtLYsiGhICd7Ul9zLGc3edn85LbD3Skb7ERx6MakRnYep3FzagZJhn14QEaZCx6\n"
"3Qs0Ir4rSP7hmlpYt8VO/zqqNR3tsA59O0D9c7bpQ7UCAwEAAaNQME4wHQYDVR0O\n"
"BBYEFAZfXccWr2L4LW5xA4ig1h0rBH+6MB8GA1UdIwQYMBaAFAZfXccWr2L4LW5x\n"
"A4ig1h0rBH+6MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAKvmt2m1o\n"
"axGKc0DjiJPypU/NsAf4Yu0nOnY8pHqJJCB0AWVoAPM7vGYPWpeH7LSdGZLuT9eK\n"
"FUWGJhPnkrnklmBdVB0l7qXYjR5uf766HDkoDxuLhNifow3IYvsS+L2Y6puRQb9w\n"
"HLMDE29mBDl0WyoX3h0yR0EiAO15V9A7I10=\n"
"-----END CERTIFICATE-----\n"
"\n"
"AddTrust External Root used for *.linphone.org\n"
"======================\n"
"-----BEGIN CERTIFICATE-----\n"
"MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML\n"
"QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD\n"
"VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw\n"
"NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU\n"
"cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg\n"
"Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821\n"
"+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw\n"
"Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo\n"
"aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy\n"
"2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7\n"
"7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P\n"
"BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL\n"
"VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk\n"
"VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB\n"
"IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl\n"
"j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5\n"
"6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355\n"
"e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u\n"
"G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=\n"
214
"-----END CERTIFICprocess_auth_requestedATE-----\n";
215

216
static void process_auth_requested(void *user_ctx, belle_sip_auth_event_t *event){
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
    BELLESIP_UNUSED(user_ctx);
    if (belle_sip_auth_event_get_mode(event) == BELLE_SIP_AUTH_MODE_HTTP_DIGEST) {
        const char *username = belle_sip_auth_event_get_username(event);
        const char *realm = belle_sip_auth_event_get_realm(event);
        belle_sip_message("process_auth_requested requested for [%s@%s]"
                          ,username?username:""
                          ,realm?realm:"");
        belle_sip_auth_event_set_passwd(event,"secret");
    } else if (belle_sip_auth_event_get_mode(event) == BELLE_SIP_AUTH_MODE_TLS) {
        const char *distinguished_name = NULL;
        belle_sip_certificates_chain_t* cert = belle_sip_certificates_chain_parse(belle_sip_tester_client_cert,strlen(belle_sip_tester_client_cert),BELLE_SIP_CERTIFICATE_RAW_FORMAT_PEM);
        belle_sip_signing_key_t* key = belle_sip_signing_key_parse(belle_sip_tester_private_key,strlen(belle_sip_tester_private_key),belle_sip_tester_private_key_passwd);
        belle_sip_auth_event_set_client_certificates_chain(event,cert);
        belle_sip_auth_event_set_signing_key(event,key);
        distinguished_name = belle_sip_auth_event_get_distinguished_name(event);
        belle_sip_message("process_auth_requested requested for  DN[%s]",distinguished_name?distinguished_name:"");
        
    } else {
        belle_sip_error("Unexpected auth mode");
    }
}

static void process_auth_requested_for_algorithm(void *user_ctx, belle_sip_auth_event_t *event){
240
    const char** client;
241
    client = (const char** ) user_ctx; //*client is algorithm of client, *(client+1) is password haché
242 243
    if(*client==NULL)
        *client = "MD5";
244 245 246 247 248 249 250 251
    if (belle_sip_auth_event_get_mode(event) == BELLE_SIP_AUTH_MODE_HTTP_DIGEST) {
        const char *username = belle_sip_auth_event_get_username(event);
        const char *realm = belle_sip_auth_event_get_realm(event);
        belle_sip_message("process_auth_requested requested for [%s@%s]"
                          ,username?username:""
                          ,realm?realm:"");
        /* Default algorithm is MD5 if it's NULL. If algorithm of client = algorithm of server (event->algorithm), set ha1 or passwd. */
        if (((event->algorithm)&&(!strcmp(*client,event->algorithm)))||((event->algorithm==NULL)&&(!strcmp(*client, "MD5")))){
252 253 254 255 256
            if(*(client+1))
                belle_sip_auth_event_set_ha1(event, *(client+1));
            else
                belle_sip_auth_event_set_passwd(event,"secret");
        }
257 258 259 260 261 262 263 264 265 266 267 268
    } else if (belle_sip_auth_event_get_mode(event) == BELLE_SIP_AUTH_MODE_TLS) {
        const char *distinguished_name = NULL;
        belle_sip_certificates_chain_t* cert = belle_sip_certificates_chain_parse(belle_sip_tester_client_cert,strlen(belle_sip_tester_client_cert),BELLE_SIP_CERTIFICATE_RAW_FORMAT_PEM);
        belle_sip_signing_key_t* key = belle_sip_signing_key_parse(belle_sip_tester_private_key,strlen(belle_sip_tester_private_key),belle_sip_tester_private_key_passwd);
        belle_sip_auth_event_set_client_certificates_chain(event,cert);
        belle_sip_auth_event_set_signing_key(event,key);
        distinguished_name = belle_sip_auth_event_get_distinguished_name(event);
        belle_sip_message("process_auth_requested requested for  DN[%s]",distinguished_name?distinguished_name:"");
        
    } else {
        belle_sip_error("Unexpected auth mode");
    }
269
}
270

271
int register_before_all(void) {
272
	belle_sip_listening_point_t *lp;
jehan's avatar
jehan committed
273
	stack=belle_sip_stack_new(NULL);
274
    const char* client[2] = {NULL, NULL};
275 276 277
	if (userhostsfile)
		belle_sip_stack_set_dns_user_hosts_file(stack,userhostsfile);
	
278
	lp=belle_sip_stack_create_listening_point(stack,"0.0.0.0",7060,"UDP");
279
	prov=belle_sip_stack_create_provider(stack,lp);
280

281 282
	lp=belle_sip_stack_create_listening_point(stack,"0.0.0.0",7060,"TCP");
	belle_sip_provider_add_listening_point(prov,lp);
283
	lp=belle_sip_stack_create_listening_point(stack,"0.0.0.0",7061,"TLS");
jehan's avatar
jehan committed
284
	if (lp) {
285
		belle_tls_crypto_config_t *crypto_config=belle_tls_crypto_config_new();
286 287
	
		belle_tls_crypto_config_set_root_ca_data(crypto_config, belle_sip_tester_root_ca);
288
		belle_sip_tls_listening_point_set_crypto_config(BELLE_SIP_TLS_LISTENING_POINT(lp), crypto_config);
jehan's avatar
jehan committed
289
		belle_sip_provider_add_listening_point(prov,lp);
jehan's avatar
jehan committed
290
		belle_sip_object_unref(crypto_config);
jehan's avatar
jehan committed
291
	}
jehan's avatar
jehan committed
292

293 294 295 296 297 298
	listener_callbacks.process_dialog_terminated=process_dialog_terminated;
	listener_callbacks.process_io_error=process_io_error;
	listener_callbacks.process_request_event=process_request_event;
	listener_callbacks.process_response_event=process_response_event;
	listener_callbacks.process_timeout=process_timeout;
	listener_callbacks.process_transaction_terminated=process_transaction_terminated;
299
	listener_callbacks.process_auth_requested=process_auth_requested_for_algorithm;
300
	listener_callbacks.listener_destroyed=NULL;
301 302
    
	listener=belle_sip_listener_create_from_callbacks(&listener_callbacks,client);
jehan's avatar
jehan committed
303 304
	return 0;
}
Ghislain MARY's avatar
Ghislain MARY committed
305

306
int register_after_all(void) {
307
	belle_sip_object_unref(prov);
jehan's avatar
jehan committed
308
	belle_sip_object_unref(stack);
309
	belle_sip_object_unref(listener);
jehan's avatar
jehan committed
310 311
	return 0;
}
jehan's avatar
jehan committed
312 313 314 315 316 317

void unregister_user(belle_sip_stack_t * stack
					,belle_sip_provider_t *prov
					,belle_sip_request_t* initial_request
					,int use_transaction) {
	belle_sip_request_t *req;
318 319 320
	belle_sip_header_cseq_t* cseq;
	belle_sip_header_expires_t* expires_header;
	int i;
jehan's avatar
jehan committed
321 322 323 324
	belle_sip_provider_add_sip_listener(prov,l);
	is_register_ok=0;
	using_transaction=0;
	req=(belle_sip_request_t*)belle_sip_object_clone((belle_sip_object_t*)initial_request);
325
	belle_sip_object_ref(req);
326
	cseq=(belle_sip_header_cseq_t*)belle_sip_message_get_header((belle_sip_message_t*)req,BELLE_SIP_CSEQ);
jehan's avatar
jehan committed
327
	belle_sip_header_cseq_set_seq_number(cseq,belle_sip_header_cseq_get_seq_number(cseq)+2); /*+2 if initial reg was challenged*/
328
	expires_header=(belle_sip_header_expires_t*)belle_sip_message_get_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_EXPIRES);
jehan's avatar
jehan committed
329 330
	belle_sip_header_expires_set_expires(expires_header,0);
	if (use_transaction){
331
		belle_sip_client_transaction_t *t;
332
		belle_sip_provider_add_authorization(prov,req,NULL,NULL,NULL,NULL); /*just in case*/
333
		t=belle_sip_provider_create_client_transaction(prov,req);
jehan's avatar
jehan committed
334 335
		belle_sip_client_transaction_send_request(t);
	}else belle_sip_provider_send_request(prov,req);
336 337 338 339 340 341 342 343
	for(i=0;!is_register_ok && i<20 ;i++) {
		belle_sip_stack_sleep(stack,500);
		if (!use_transaction && !is_register_ok) {
			belle_sip_object_ref(req);
			belle_sip_provider_send_request(prov,req); /*manage retransmitions*/
		}
	}

344 345
	BC_ASSERT_EQUAL(is_register_ok,1,int,"%d");
	BC_ASSERT_EQUAL(using_transaction,use_transaction,int,"%d");
346
	belle_sip_object_unref(req);
jehan's avatar
jehan committed
347 348
	belle_sip_provider_remove_sip_listener(prov,l);
}
Ghislain MARY's avatar
Ghislain MARY committed
349

jehan's avatar
jehan committed
350
belle_sip_request_t* try_register_user_at_domain(belle_sip_stack_t * stack
351 352 353 354 355 356 357
	,belle_sip_provider_t *prov
	,const char *transport
	,int use_transaction
	,const char* username
	,const char* domain
	,const char* outbound_proxy
	,int success_expected) {
358
	belle_sip_request_t *req,*copy;
359 360
	char identity[256];
	char uri[256];
361
	int i;
Simon Morlat's avatar
Simon Morlat committed
362
	char *outbound=NULL;
363
	int do_manual_retransmissions = FALSE;
364

365
	number_of_challenge=0;
366
	if (transport)
367 368
		snprintf(uri,sizeof(uri),"sip:%s;transport=%s",domain,transport);
	else snprintf(uri,sizeof(uri),"sip:%s",domain);
jehan's avatar
jehan committed
369

Simon Morlat's avatar
Simon Morlat committed
370 371
	if (transport && strcasecmp("tls",transport)==0 && belle_sip_provider_get_listening_point(prov,"tls")==NULL){
		belle_sip_error("No TLS support, test skipped.");
jehan's avatar
jehan committed
372
		return NULL;
Simon Morlat's avatar
Simon Morlat committed
373
	}
374

Simon Morlat's avatar
Simon Morlat committed
375
	if (outbound_proxy){
jehan's avatar
jehan committed
376
		if (strstr(outbound_proxy,"sip:")==NULL && strstr(outbound_proxy,"sips:")==NULL){
Simon Morlat's avatar
Simon Morlat committed
377 378 379
			outbound=belle_sip_strdup_printf("sip:%s",outbound_proxy);
		}else outbound=belle_sip_strdup(outbound_proxy);
	}
Simon Morlat's avatar
Simon Morlat committed
380

381
	snprintf(identity,sizeof(identity),"Tester <sip:%s@%s>",username,domain);
Simon Morlat's avatar
Simon Morlat committed
382
	req=belle_sip_request_create(
383 384 385 386 387 388 389 390
						belle_sip_uri_parse(uri),
						"REGISTER",
						belle_sip_provider_create_call_id(prov),
						belle_sip_header_cseq_create(20,"REGISTER"),
						belle_sip_header_from_create2(identity,BELLE_SIP_RANDOM_TAG),
						belle_sip_header_to_create2(identity,NULL),
						belle_sip_header_via_new(),
						70);
391
	belle_sip_object_ref(req);
jehan's avatar
jehan committed
392
	is_register_ok=0;
393
	io_error_count=0;
394
	using_transaction=0;
jehan's avatar
jehan committed
395
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(600)));
396
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_contact_new()));
397
	copy=(belle_sip_request_t*)belle_sip_object_ref(belle_sip_object_clone((belle_sip_object_t*)req));
jehan's avatar
jehan committed
398
	belle_sip_provider_add_sip_listener(prov,l=BELLE_SIP_LISTENER(listener));
399 400
	if (use_transaction){
		belle_sip_client_transaction_t *t=belle_sip_provider_create_client_transaction(prov,req);
Simon Morlat's avatar
Simon Morlat committed
401
		belle_sip_client_transaction_send_request_to(t,outbound?belle_sip_uri_parse(outbound):NULL);
402 403
	}else{
		belle_sip_provider_send_request(prov,req);
404
		do_manual_retransmissions = (transport == NULL) || (strcasecmp(transport,"udp") == 0);
405
	}
406 407
	for(i=0;!is_register_ok && i<20 && io_error_count==0;i++) {
		belle_sip_stack_sleep(stack,500);
408
		if (do_manual_retransmissions && !is_register_ok) {
409 410 411 412
			belle_sip_object_ref(req);
			belle_sip_provider_send_request(prov,req); /*manage retransmitions*/
		}
	}
413 414
	BC_ASSERT_EQUAL(is_register_ok,success_expected,int,"%d");
	if (success_expected) BC_ASSERT_EQUAL(using_transaction,use_transaction,int,"%d");
415

416
	belle_sip_object_unref(req);
jehan's avatar
jehan committed
417
	belle_sip_provider_remove_sip_listener(prov,l);
Simon Morlat's avatar
Simon Morlat committed
418
	if (outbound) belle_sip_free(outbound);
419
	return copy;
Simon Morlat's avatar
Simon Morlat committed
420
}
Ghislain MARY's avatar
Ghislain MARY committed
421

jehan's avatar
jehan committed
422 423 424 425 426
belle_sip_request_t* register_user_at_domain(belle_sip_stack_t * stack
					,belle_sip_provider_t *prov
					,const char *transport
					,int use_transaction
					,const char* username
427
					,const char* domain
Simon Morlat's avatar
Simon Morlat committed
428 429
					,const char* outbound) {
	return try_register_user_at_domain(stack,prov,transport,use_transaction,username,domain,outbound,1);
430

jehan's avatar
jehan committed
431
}
Ghislain MARY's avatar
Ghislain MARY committed
432

433 434 435 436
belle_sip_request_t* register_user(belle_sip_stack_t * stack
					,belle_sip_provider_t *prov
					,const char *transport
					,int use_transaction
437
					,const char* username
Simon Morlat's avatar
Simon Morlat committed
438 439
					,const char* outbound) {
	return register_user_at_domain(stack,prov,transport,use_transaction,username,test_domain,outbound);
440
}
441

Simon Morlat's avatar
Simon Morlat committed
442
static void register_with_outbound(const char *transport, int use_transaction,const char* outbound ) {
jehan's avatar
jehan committed
443
	belle_sip_request_t *req;
444

Simon Morlat's avatar
Simon Morlat committed
445
	req=register_user(stack, prov, transport,use_transaction,"tester",outbound);
446 447 448 449
	if (req) {
		unregister_user(stack,prov,req,use_transaction);
		belle_sip_object_unref(req);
	}
jehan's avatar
jehan committed
450
}
Ghislain MARY's avatar
Ghislain MARY committed
451

452
static void register_test(const char *transport, int use_transaction) {
Simon Morlat's avatar
Simon Morlat committed
453
	register_with_outbound(transport,use_transaction,NULL);
454
}
Ghislain MARY's avatar
Ghislain MARY committed
455

456 457
static void stateless_register_udp(void){
	register_test(NULL,0);
jehan's avatar
jehan committed
458
}
459

jehan's avatar
jehan committed
460 461 462 463
static void stateless_register_tls(void){
	register_test("tls",0);
}

464 465 466 467 468 469 470
static void stateless_register_tcp(void){
	register_test("tcp",0);
}

static void stateful_register_udp(void){
	register_test(NULL,1);
}
Ghislain MARY's avatar
Ghislain MARY committed
471

472
static void stateful_register_udp_with_keep_alive(void) {
jehan's avatar
jehan committed
473 474 475 476 477
	belle_sip_listening_point_set_keep_alive(belle_sip_provider_get_listening_point(prov,"udp"),200);
	register_test(NULL,1);
	belle_sip_main_loop_sleep(belle_sip_stack_get_main_loop(stack),500);
	belle_sip_listening_point_set_keep_alive(belle_sip_provider_get_listening_point(prov,"udp"),-1);
}
Ghislain MARY's avatar
Ghislain MARY committed
478

Simon Morlat's avatar
Simon Morlat committed
479 480
static void stateful_register_udp_with_outbound_proxy(void){
	register_with_outbound("udp",1,test_domain);
481 482
}

Simon Morlat's avatar
Simon Morlat committed
483
static void stateful_register_udp_delayed(void){
484
	belle_sip_stack_set_tx_delay(stack,3000);
Simon Morlat's avatar
Simon Morlat committed
485 486 487 488
	register_test(NULL,1);
	belle_sip_stack_set_tx_delay(stack,0);
}

489
static void stateful_register_udp_with_send_error(void){
490
	belle_sip_request_t *req;
491
	belle_sip_stack_set_send_error(stack,-1);
492
	req=try_register_user_at_domain(stack, prov, NULL,1,"tester",test_domain,NULL,0);
493
	belle_sip_stack_set_send_error(stack,0);
494
	if (req) belle_sip_object_unref(req);
495 496
}

497 498
static void stateful_register_tcp(void){
	register_test("tcp",1);
jehan's avatar
jehan committed
499
}
Simon Morlat's avatar
Simon Morlat committed
500

501 502 503
static void stateful_register_tls(void){
	register_test("tls",1);
}
jehan's avatar
jehan committed
504

505 506 507 508 509 510 511
static void stateful_register_tls_with_wrong_cname(void){
	belle_sip_request_t *req;
	
	req = try_register_user_at_domain(stack, prov, "tls", 1, "tester",test_domain, test_with_wrong_cname, 0);
	if (req) belle_sip_object_unref(req);
}

512 513 514 515 516 517
static void stateful_register_tls_with_http_proxy(void) {
	belle_sip_tls_listening_point_t * lp = (belle_sip_tls_listening_point_t*)belle_sip_provider_get_listening_point(prov, "tls");
	if (!lp) {
		belle_sip_error("No TLS support, test skipped.");
		return;
	}
518
	belle_sip_provider_clean_channels(prov);
519 520
	belle_sip_stack_set_http_proxy_host(stack, test_http_proxy_addr);
	belle_sip_stack_set_http_proxy_port(stack, test_http_proxy_port);
521
	register_test("tls",1);
522 523
	belle_sip_stack_set_http_proxy_host(stack, NULL);
	belle_sip_stack_set_http_proxy_port(stack, 0);
524 525 526 527

}

static void stateful_register_tls_with_wrong_http_proxy(void){
528

529 530 531 532 533
	belle_sip_tls_listening_point_t * lp = (belle_sip_tls_listening_point_t*)belle_sip_provider_get_listening_point(prov, "tls");
	if (!lp) {
		belle_sip_error("No TLS support, test skipped.");
		return;
	}
534
	belle_sip_provider_clean_channels(prov);
535 536
	belle_sip_stack_set_http_proxy_host(stack, "mauvaisproxy.linphone.org");
	belle_sip_stack_set_http_proxy_port(stack, test_http_proxy_port);
537
	try_register_user_at_domain(stack,prov,"tls",1,"tester",test_domain,NULL,0);
538 539
	belle_sip_stack_set_http_proxy_host(stack, NULL);
	belle_sip_stack_set_http_proxy_port(stack, 0);
540

541 542 543
}


jehan's avatar
jehan committed
544
static void bad_req_process_io_error(void *user_ctx, const belle_sip_io_error_event_t *event){
545 546
	BELLESIP_UNUSED(user_ctx);
	BELLESIP_UNUSED(event);
jehan's avatar
jehan committed
547 548
	belle_sip_message("bad_req_process_io_error not implemented yet");
}
Ghislain MARY's avatar
Ghislain MARY committed
549

jehan's avatar
jehan committed
550
static void bad_req_process_response_event(void *user_ctx, const belle_sip_response_event_t *event){
551
	belle_sip_response_t *resp=belle_sip_response_event_get_response(event);
jehan's avatar
jehan committed
552 553
	int *bad_request_response_received=(int*)user_ctx;
	if (belle_sip_response_event_get_client_transaction(event) != NULL) {
554 555
		BC_ASSERT_PTR_NOT_NULL(resp);
		BC_ASSERT_EQUAL(belle_sip_response_get_status_code(resp),400,int,"%d");
jehan's avatar
jehan committed
556 557 558
		*bad_request_response_received=1;
		belle_sip_main_loop_quit(belle_sip_stack_get_main_loop(stack));
	}
jehan's avatar
jehan committed
559 560
}

561
static void test_bad_request(void) {
jehan's avatar
jehan committed
562
	belle_sip_request_t *req;
563 564
	belle_sip_listener_t *bad_req_listener;
	belle_sip_client_transaction_t *t;
jehan's avatar
jehan committed
565 566 567 568
	belle_sip_header_address_t* route_address=belle_sip_header_address_create(NULL,belle_sip_uri_create(NULL,test_domain));
	belle_sip_header_route_t* route;
	belle_sip_header_to_t* to = belle_sip_header_to_create2("sip:toto@titi.com",NULL);
	belle_sip_listener_callbacks_t cbs;
569
	belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(prov,"TCP");
570
	int bad_request_response_received=0;
jehan's avatar
jehan committed
571 572 573 574
	memset(&cbs,0,sizeof(cbs));

	cbs.process_io_error=bad_req_process_io_error;
	cbs.process_response_event=bad_req_process_response_event;
575

576
	bad_req_listener = belle_sip_listener_create_from_callbacks(&cbs,&bad_request_response_received);
jehan's avatar
jehan committed
577 578

	req=belle_sip_request_create(
579 580 581 582 583 584 585 586
						BELLE_SIP_URI(belle_sip_object_clone(BELLE_SIP_OBJECT(belle_sip_header_address_get_uri(route_address)))),
						"REGISTER",
						belle_sip_provider_create_call_id(prov),
						belle_sip_header_cseq_create(20,"REGISTER"),
						belle_sip_header_from_create2("sip:toto@titi.com",BELLE_SIP_RANDOM_TAG),
						to,
						belle_sip_header_via_new(),
						70);
jehan's avatar
jehan committed
587 588 589 590 591 592 593 594 595

	belle_sip_uri_set_transport_param(belle_sip_header_address_get_uri(route_address),"tcp");
	route = belle_sip_header_route_create(route_address);
	belle_sip_header_set_name(BELLE_SIP_HEADER(to),"BrokenHeader");

	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_expires_create(600)));
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(route));
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(req),BELLE_SIP_HEADER(belle_sip_header_contact_new()));
	belle_sip_provider_add_sip_listener(prov,bad_req_listener);
596
	t=belle_sip_provider_create_client_transaction(prov,req);
jehan's avatar
jehan committed
597
	belle_sip_client_transaction_send_request(t);
598
	belle_sip_stack_sleep(stack,3000);
599
	BC_ASSERT_EQUAL(bad_request_response_received,1,int,"%d");
jehan's avatar
jehan committed
600
	belle_sip_provider_remove_sip_listener(prov,bad_req_listener);
601
	belle_sip_object_unref(bad_req_listener);
602

603
	belle_sip_listening_point_clean_channels(lp);
jehan's avatar
jehan committed
604
}
Simon Morlat's avatar
Simon Morlat committed
605

606

607
static void test_register_authenticate(void) {
608
	belle_sip_request_t *reg;
609
	number_of_challenge=0;
610
	authorized_request=NULL;
611
	reg=register_user_at_domain(stack, prov, "udp",1,"bellesip",auth_domain,NULL);
612 613 614 615 616
	if (authorized_request) {
		unregister_user(stack,prov,authorized_request,1);
		belle_sip_object_unref(authorized_request);
	}
	belle_sip_object_unref(reg);
617
}
jehan's avatar
jehan committed
618

619 620
static void test_register_channel_inactive(void){
	belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(prov,"TCP");
621 622 623 624 625 626 627
	BC_ASSERT_PTR_NOT_NULL(lp);
	if (lp) {
		belle_sip_stack_set_inactive_transport_timeout(stack,5);
		belle_sip_listening_point_clean_channels(lp);
		BC_ASSERT_EQUAL(belle_sip_listening_point_get_channel_count(lp),0,int,"%d");
		register_test("tcp",1);
		BC_ASSERT_EQUAL(belle_sip_listening_point_get_channel_count(lp),1,int,"%d");
628 629 630 631 632 633
		belle_sip_stack_sleep(stack, 3000);
		BC_ASSERT_EQUAL(belle_sip_listening_point_get_channel_count(lp),1,int,"%d");
		register_test("tcp",1);
		belle_sip_stack_sleep(stack, 3000);
		BC_ASSERT_EQUAL(belle_sip_listening_point_get_channel_count(lp),1,int,"%d");
		belle_sip_stack_sleep(stack,3000);
634 635 636
		BC_ASSERT_EQUAL(belle_sip_listening_point_get_channel_count(lp),0,int,"%d");
		belle_sip_stack_set_inactive_transport_timeout(stack,3600);
	}
637
}
jehan's avatar
jehan committed
638

639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
static void test_channel_moving_to_error_and_cleaned(void){
	belle_sip_listening_point_t *lp=belle_sip_provider_get_listening_point(prov,"UDP");
	BC_ASSERT_PTR_NOT_NULL(lp);
	if (lp) {
		belle_sip_request_t *req;
		belle_sip_client_transaction_t *tr;
		char identity[128];
		char uri[128];
		
		belle_sip_listening_point_clean_channels(lp);
		BC_ASSERT_EQUAL(belle_sip_listening_point_get_channel_count(lp),0,int,"%d");
		
		snprintf(identity,sizeof(identity),"Tester <sip:%s@%s>","bellesip",test_domain);
		snprintf(uri,sizeof(uri),"sip:%s",test_domain);
		req = belle_sip_request_create(
						belle_sip_uri_parse(uri),
						"REGISTER",
						belle_sip_provider_create_call_id(prov),
						belle_sip_header_cseq_create(20,"REGISTER"),
						belle_sip_header_from_create2(identity,BELLE_SIP_RANDOM_TAG),
						belle_sip_header_to_create2(identity,NULL),
						belle_sip_header_via_new(),
						70);
		tr = belle_sip_provider_create_client_transaction(prov, req);
		belle_sip_client_transaction_send_request(tr);
		belle_sip_object_ref(tr);
		BC_ASSERT_EQUAL(belle_sip_listening_point_get_channel_count(lp),1,int,"%d");
		/*calling notify_server_error() will make the channel enter the error state, which is what we want to test*/
		belle_sip_channel_notify_server_error((belle_sip_channel_t*)lp->channels->data);
		/*immediately after, we clean the channel from the listening point*/
		belle_sip_listening_point_clean_channels(lp);
		/*we just want to verify that it doesn't crash*/
		belle_sip_stack_sleep(stack, 1000);
		belle_sip_object_unref(tr);
		
	}
}

jehan's avatar
jehan committed
677 678 679 680 681


static void test_register_client_authenticated(void) {
	belle_sip_request_t *reg;
	authorized_request=NULL;
682

Simon Morlat's avatar
Simon Morlat committed
683
	reg=register_user_at_domain(stack, prov, "tls",1,"tester",client_auth_domain,client_auth_outbound_proxy);
jehan's avatar
jehan committed
684 685 686 687
	if (authorized_request) {
		unregister_user(stack,prov,authorized_request,1);
		belle_sip_object_unref(authorized_request);
	}
688
	if (reg) belle_sip_object_unref(reg);
jehan's avatar
jehan committed
689 690
}

691 692 693 694
static void test_connection_failure(void){
	belle_sip_request_t *req;
	io_error_count=0;
	req=try_register_user_at_domain(stack, prov, "TCP",1,"tester","sip.linphone.org",no_server_running_here,0);
695
	BC_ASSERT_GREATER(io_error_count,1,int,"%d");
696 697 698
	if (req) belle_sip_object_unref(req);
}

699
static void test_connection_too_long(const char *transport){
700 701
	belle_sip_request_t *req;
	int orig=belle_sip_stack_get_transport_timeout(stack);
702
	char *no_response_here_with_transport = belle_sip_strdup_printf(no_response_here, transport);
703
	io_error_count=0;
704 705 706 707
	if (transport && strcasecmp("tls",transport)==0 && belle_sip_provider_get_listening_point(prov,"tls")==NULL){
		belle_sip_error("No TLS support, test skipped.");
		return;
	}
708
	belle_sip_stack_set_transport_timeout(stack,2000);
709
	req=try_register_user_at_domain(stack, prov, transport,1,"tester","sip.linphone.org",no_response_here_with_transport,0);
710
	BC_ASSERT_GREATER(io_error_count, 1, int, "%d");
711
	belle_sip_stack_set_transport_timeout(stack,orig);
712
	belle_sip_free(no_response_here_with_transport);
713 714 715
	if (req) belle_sip_object_unref(req);
}

716 717 718 719 720 721 722 723
static void test_connection_too_long_tcp(void){
	test_connection_too_long("tcp");
}

static void test_connection_too_long_tls(void){
	test_connection_too_long("tls");
}

724 725 726
static void test_tls_to_tcp(void){
	belle_sip_request_t *req;
	int orig=belle_sip_stack_get_transport_timeout(stack);
727
	io_error_count=0;
728 729 730
	belle_sip_stack_set_transport_timeout(stack,2000);
	req=try_register_user_at_domain(stack, prov, "TLS",1,"tester",test_domain,test_domain_tls_to_tcp,0);
	if (req){
731
		BC_ASSERT_GREATER(io_error_count,1,int,"%d");
732 733 734 735
		belle_sip_object_unref(req);
	}
	belle_sip_stack_set_transport_timeout(stack,orig);
}
jehan's avatar
jehan committed
736

737
static void register_dns_srv_tcp(void){
738 739 740
	belle_sip_request_t *req;
	io_error_count=0;
	req=try_register_user_at_domain(stack, prov, "TCP",1,"tester",client_auth_domain,"sip:linphone.net;transport=tcp",1);
741
	BC_ASSERT_EQUAL(io_error_count,0,int,"%d");
742 743 744
	if (req) belle_sip_object_unref(req);
}

745 746 747 748 749 750 751 752 753
static void enable_cn_mismatch(int enable){
	belle_sip_listening_point_t *lp =  belle_sip_provider_get_listening_point(prov, "TLS");
	belle_sip_provider_clean_channels(prov);
	if (lp) {
		belle_tls_crypto_config_t *cfg = belle_sip_tls_listening_point_get_crypto_config(BELLE_SIP_TLS_LISTENING_POINT(lp));
		belle_tls_crypto_config_set_verify_exceptions(cfg, enable ? BELLE_TLS_VERIFY_CN_MISMATCH : 0);
	}
}

754 755 756
static void register_dns_srv_tls(void){
	belle_sip_request_t *req;
	io_error_count=0;
757
	enable_cn_mismatch(TRUE);
758
	req=try_register_user_at_domain(stack, prov, "TLS",1,"tester",client_auth_domain,"sip:linphone.net;transport=tls",1);
759
	BC_ASSERT_EQUAL(io_error_count, 0, int, "%d");
760
	if (req) belle_sip_object_unref(req);
761
	enable_cn_mismatch(FALSE);
762 763
}

764 765 766 767 768 769 770 771
static void register_dns_srv_tls_with_http_proxy(void){
	belle_sip_request_t *req;
	belle_sip_tls_listening_point_t * lp = (belle_sip_tls_listening_point_t*)belle_sip_provider_get_listening_point(prov, "tls");
	if (!lp) {
		belle_sip_error("No TLS support, test skipped.");
		return;
	}
	io_error_count=0;
772
	enable_cn_mismatch(TRUE);
773 774
	belle_sip_stack_set_http_proxy_host(stack, test_http_proxy_addr);
	belle_sip_stack_set_http_proxy_port(stack, test_http_proxy_port);
775
	req=try_register_user_at_domain(stack, prov, "TLS",1,"tester",client_auth_domain,"sip:linphone.net;transport=tls",1);
776 777
	belle_sip_stack_set_http_proxy_host(stack, NULL);
	belle_sip_stack_set_http_proxy_port(stack, 0);
778 779
	BC_ASSERT_EQUAL(io_error_count, 0, int, "%d");
	if (req) belle_sip_object_unref(req);
780
	enable_cn_mismatch(FALSE);
781 782
}

783 784 785 786
static void register_dns_load_balancing(void) {
	belle_sip_request_t *req;
	io_error_count = 0;
	req = try_register_user_at_domain(stack, prov, "TCP", 1, "tester", client_auth_domain, "sip:belle-sip.net;transport=tcp", 1);
787
	BC_ASSERT_EQUAL(io_error_count, 0, int, "%d");
788 789 790
	if (req) belle_sip_object_unref(req);
}

791 792 793
static void process_message_response_event(void *user_ctx, const belle_sip_response_event_t *event){
	int status;
	BELLESIP_UNUSED(user_ctx);
794 795 796 797 798 799 800 801 802
	if (BC_ASSERT_PTR_NOT_NULL(belle_sip_response_event_get_response(event))) {
		belle_sip_message("process_response_event [%i] [%s]"
						,status=belle_sip_response_get_status_code(belle_sip_response_event_get_response(event))
						,belle_sip_response_get_reason_phrase(belle_sip_response_event_get_response(event)));

		if (status >= 200){
			is_register_ok=status;
			belle_sip_main_loop_quit(belle_sip_stack_get_main_loop(stack));
		}
803 804
	}
}
jehan's avatar
jehan committed
805
static belle_sip_request_t* send_message_to(belle_sip_request_t *initial_request, const char* realm, belle_sip_uri_t *outbound){
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831
	int i;
	int io_error_count=0;
	belle_sip_request_t *message_request=NULL;
	belle_sip_request_t *clone_request=NULL;
	// belle_sip_header_authorization_t * h=NULL;

	is_register_ok = 0;

	message_request=belle_sip_request_create(
								belle_sip_uri_parse("sip:sip.linphone.org;transport=tcp")
								,"MESSAGE"
								,belle_sip_provider_create_call_id(prov)
								,belle_sip_header_cseq_create(22,"MESSAGE")
								,belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(initial_request), belle_sip_header_from_t)
								,belle_sip_header_to_parse("To: sip:marie@sip.linphone.org")
								,belle_sip_header_via_new()
								,70);
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(message_request),BELLE_SIP_HEADER(belle_sip_header_expires_create(600)));
	belle_sip_message_add_header(BELLE_SIP_MESSAGE(message_request),BELLE_SIP_HEADER(belle_sip_header_contact_new()));
	belle_sip_provider_add_authorization(prov,message_request,NULL,NULL,NULL,realm);
	// h = belle_sip_message_get_header_by_type(BELLE_SIP_MESSAGE(message_request), belle_sip_header_authorization_t);
	/*if a matching authorization was found, use it as a proxy authorization*/
	// if (h != NULL){
	// 	belle_sip_header_set_name(BELLE_SIP_HEADER(h), BELLE_SIP_PROXY_AUTHORIZATION);
	// }
	clone_request = (belle_sip_request_t*)belle_sip_object_ref(belle_sip_object_clone((belle_sip_object_t*)message_request));
jehan's avatar
jehan committed
832
	belle_sip_client_transaction_send_request_to(belle_sip_provider_create_client_transaction(prov,message_request),outbound);
833 834 835 836 837
	for(i=0; i<2 && io_error_count==0 &&is_register_ok==0;i++)
		belle_sip_stack_sleep(stack,5000);

	return clone_request;
}
jehan's avatar
jehan committed
838 839

static void reuse_nonce_base(const char* outbound) {
840
	belle_sip_request_t *register_request;
jehan's avatar
jehan committed
841 842 843 844 845 846 847 848 849 850
	size_t initial_auth_context_count=0;/*belle_sip_list_size(prov->auth_contexts);*/
	char outbound_uri[256];
	/*reset auth context*/
	prov->auth_contexts = belle_sip_list_free_with_data(prov->auth_contexts,(void(*)(void*))belle_sip_authorization_destroy);
	
	if (outbound)
		snprintf(outbound_uri, sizeof(outbound_uri),"sip:%s",outbound);
	
	register_request=register_user_at_domain(stack, prov, "tcp",1,"marie",outbound,NULL);
	
851 852 853
	if (register_request) {
		belle_sip_header_authorization_t * h = NULL;
		belle_sip_request_t *message_request;
jehan's avatar
jehan committed
854 855 856 857 858 859 860 861 862 863 864 865 866
		belle_sip_listener_callbacks_t cbs;
		belle_sip_listener_t *reuse_nonce_listener;
		cbs.process_dialog_terminated=process_dialog_terminated;
		cbs.process_io_error=process_io_error;
		cbs.process_request_event=process_request_event;
		cbs.process_response_event=process_message_response_event;
		cbs.process_timeout=process_timeout;
		cbs.process_transaction_terminated=process_transaction_terminated;
		cbs.process_auth_requested=process_auth_requested;
		cbs.listener_destroyed=NULL;
		reuse_nonce_listener=belle_sip_listener_create_from_callbacks(&cbs,NULL);

		belle_sip_provider_add_sip_listener(prov,BELLE_SIP_LISTENER(reuse_nonce_listener));
867 868

		/*currently only one nonce should have been used (the one for the REGISTER)*/
869
		BC_ASSERT_EQUAL((unsigned int)belle_sip_list_size(prov->auth_contexts), (unsigned int)initial_auth_context_count+1,unsigned int,"%u");
870 871

		/*this should reuse previous nonce*/
jehan's avatar
jehan committed
872
		message_request=send_message_to(register_request, auth_domain,outbound?belle_sip_uri_parse(outbound_uri):NULL);
873
		BC_ASSERT_EQUAL(is_register_ok, 404,int,"%d");
874
		h = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type(
875 876
					BELLE_SIP_MESSAGE(message_request), belle_sip_header_proxy_authorization_t
				));
jehan's avatar
jehan committed
877 878 879
		if (BC_ASSERT_PTR_NOT_NULL(h)
			&& belle_sip_header_authorization_get_qop(h)
			&& strcmp(belle_sip_header_authorization_get_qop(h),"auth")==0) {
880 881 882 883 884
			char * first_nonce_used;
			BC_ASSERT_EQUAL(2, belle_sip_header_authorization_get_nonce_count(h),int,"%d");
			first_nonce_used = belle_sip_strdup(belle_sip_header_authorization_get_nonce(h));
			belle_sip_free(first_nonce_used);
		}
885 886 887 888
		belle_sip_object_unref(message_request);


		/*new nonce should be created when not using outbound proxy realm*/
jehan's avatar
jehan committed
889
		message_request=send_message_to(register_request, NULL,outbound?belle_sip_uri_parse(outbound_uri):NULL);
890
		BC_ASSERT_EQUAL(is_register_ok, 407,int,"%d");
891 892 893
		h = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type(
				BELLE_SIP_MESSAGE(message_request), belle_sip_header_proxy_authorization_t
			));
894
		BC_ASSERT_PTR_NULL(h);
895 896 897 898
		belle_sip_object_unref(message_request);


		/*new nonce should be created here too*/
jehan's avatar
jehan committed
899
		message_request=send_message_to(register_request, "wrongrealm",outbound?belle_sip_uri_parse(outbound_uri):NULL);
900
		BC_ASSERT_EQUAL(is_register_ok, 407,int,"%d");
901 902 903
		h = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type(
				BELLE_SIP_MESSAGE(message_request), belle_sip_header_proxy_authorization_t
			));
904
		BC_ASSERT_PTR_NULL(h);
905 906 907
		belle_sip_object_unref(message_request);


jehan's avatar
jehan committed
908 909 910
		/*first nonce created should be reused. this test is only for qop = auth*/
		message_request=send_message_to(register_request, auth_domain,outbound?belle_sip_uri_parse(outbound_uri):NULL);
		
911 912 913
		h = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type(
				BELLE_SIP_MESSAGE(message_request), belle_sip_header_proxy_authorization_t
			));
jehan's avatar
jehan committed
914 915 916 917
		if (BC_ASSERT_PTR_NOT_NULL(h)
			&& belle_sip_header_authorization_get_qop(h)
			&& strcmp(belle_sip_header_authorization_get_qop(h),"auth")==0) {
			BC_ASSERT_EQUAL(is_register_ok, 404,int,"%d");
918 919
			BC_ASSERT_EQUAL(3, belle_sip_header_authorization_get_nonce_count(h),int,"%d");
		}
920 921
		belle_sip_object_unref(message_request);

jehan's avatar
jehan committed
922
		belle_sip_provider_remove_sip_listener(prov,BELLE_SIP_LISTENER(reuse_nonce_listener));
923 924 925 926
		unregister_user(stack,prov,register_request,1);
		belle_sip_object_unref(register_request);
	}
}
jehan's avatar
jehan committed
927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981
static void reuse_nonce(void) {
	reuse_nonce_base("sip.linphone.org");
}
#define NONCE_SIZE  32
void register_process_request_event(char *nonce, const belle_sip_request_event_t *event) {
	belle_sip_request_t *req = belle_sip_request_event_get_request(event);
	belle_sip_header_authorization_t *authorization;
	int response_code = 407;
	char *uri_as_string= belle_sip_uri_to_string(belle_sip_request_get_uri(req));
	belle_sip_response_t * response_msg;
	belle_sip_server_transaction_t *trans=belle_sip_provider_create_server_transaction(prov, req);
	
	if (strcasecmp(belle_sip_request_get_method(req), "REGISTER") == 0) {
		response_code=401;
	}
	
	if (	(authorization = belle_sip_message_get_header_by_type(req,belle_sip_header_authorization_t))
		 || (authorization = BELLE_SIP_HEADER_AUTHORIZATION(belle_sip_message_get_header_by_type(req,belle_sip_header_proxy_authorization_t)))) {
		 char ha1[33], ha2[33], response[33];
		belle_sip_auth_helper_compute_ha1(belle_sip_header_authorization_get_username(authorization)
										, belle_sip_header_authorization_get_realm(authorization)
										  ,"secret", ha1);
		belle_sip_auth_helper_compute_ha2(belle_sip_request_get_method(req)
										  , uri_as_string, ha2);
		belle_sip_auth_helper_compute_response(ha1,nonce, ha2, response);
		if (strcmp(response, belle_sip_header_authorization_get_response(authorization)) == 0) {
			belle_sip_message("Auth sucessfull");
			if (strcasecmp(belle_sip_request_get_method(req), "MESSAGE") == 0) {
				response_code = 404;
			} else {
				response_code = 200;
			}
		}
	}
	
	belle_sip_random_token((nonce), NONCE_SIZE);
	response_msg = belle_sip_response_create_from_request(req, response_code);
	
	if (response_code == 407 || response_code == 401 ) {
		belle_sip_header_www_authenticate_t *www_authenticate = 401?belle_sip_header_www_authenticate_new():BELLE_SIP_HEADER_WWW_AUTHENTICATE(belle_sip_header_proxy_authenticate_new());
	
		
		belle_sip_header_www_authenticate_set_realm(www_authenticate, "sip.linphone.org");
		belle_sip_header_www_authenticate_set_domain(www_authenticate, "sip:sip.linphone.org");
		belle_sip_header_www_authenticate_set_scheme(www_authenticate, "Digest");
		belle_sip_header_www_authenticate_set_nonce(www_authenticate,nonce);
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(response_msg), BELLE_SIP_HEADER(www_authenticate));
	} else {
		belle_sip_header_authentication_info_t* authentication_info = belle_sip_header_authentication_info_new();
		belle_sip_header_authentication_info_set_next_nonce(authentication_info, nonce);
		belle_sip_message_add_header(BELLE_SIP_MESSAGE(response_msg), BELLE_SIP_HEADER(authentication_info));
	}
	
	belle_sip_server_transaction_send_response(trans,response_msg);
}
982

Ghislain MARY's avatar
Ghislain MARY committed
983
static void test_register_with_next_nonce(void) {
jehan's avatar
jehan committed
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
	belle_sip_listening_point_t *server_lp = belle_sip_stack_create_listening_point(stack,"0.0.0.0",bctbx_random()%20000 +1024,"TCP");
	char  nonce [NONCE_SIZE];
	belle_sip_listener_t *server_listener;
	char listening_uri[256];
	belle_sip_listener_callbacks_t cbs;
	belle_sip_random_token((nonce), sizeof(nonce));
	
	cbs.process_dialog_terminated=NULL;
	cbs.process_io_error=NULL;
	cbs.process_request_event=(void (*)(void *user_ctx, const belle_sip_request_event_t *event))register_process_request_event;
	cbs.process_response_event=NULL;
	cbs.process_timeout=NULL;
	cbs.process_transaction_terminated=NULL;
	cbs.process_auth_requested=NULL;
	cbs.listener_destroyed=NULL;
	server_listener=belle_sip_listener_create_from_callbacks(&cbs,nonce);
	belle_sip_provider_add_sip_listener(prov,server_listener);
	belle_sip_provider_add_listening_point(prov,server_lp);
	snprintf(listening_uri,sizeof(listening_uri), "127.0.0.1:%i;transport=tcp",belle_sip_listening_point_get_port(server_lp));

	reuse_nonce_base(listening_uri);
	belle_sip_provider_remove_sip_listener(prov, server_listener);
	belle_sip_provider_remove_listening_point(prov, server_lp);
}
1008

Ghislain MARY's avatar
Ghislain MARY committed
1009
test_t register_tests[] = {
1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
	TEST_NO_TAG("Stateful UDP", stateful_register_udp),
	TEST_NO_TAG("Stateful UDP with keep-alive", stateful_register_udp_with_keep_alive),
	TEST_NO_TAG("Stateful UDP with network delay", stateful_register_udp_delayed),
	TEST_NO_TAG("Stateful UDP with send error", stateful_register_udp_with_send_error),
	TEST_NO_TAG("Stateful UDP with outbound proxy", stateful_register_udp_with_outbound_proxy),
	TEST_NO_TAG("Stateful TCP", stateful_register_tcp),
	TEST_NO_TAG("Stateful TLS", stateful_register_tls),
	TEST_NO_TAG("Stateful TLS with wrong cname", stateful_register_tls_with_wrong_cname),
	TEST_NO_TAG("Stateful TLS with http proxy", stateful_register_tls_with_http_proxy),
	TEST_NO_TAG("Stateful TLS with wrong http proxy", stateful_register_tls_with_wrong_http_proxy),
	TEST_NO_TAG("Stateless UDP", stateless_register_udp),
	TEST_NO_TAG("Stateless TCP", stateless_register_tcp),
	TEST_NO_TAG("Stateless TLS", stateless_register_tls),
	TEST_NO_TAG("Bad TCP request", test_bad_request),
	TEST_NO_TAG("Authenticate", test_register_authenticate),
	TEST_NO_TAG("TLS client cert authentication", test_register_client_authenticated),
	TEST_NO_TAG("Channel inactive", test_register_channel_inactive),
1027
	TEST_NO_TAG("Channel moving to error test and cleaned", test_channel_moving_to_error_and_cleaned),
1028 1029 1030 1031 1032 1033 1034 1035
	TEST_NO_TAG("TCP connection failure", test_connection_failure),
	TEST_NO_TAG("TCP connection too long", test_connection_too_long_tcp),
	TEST_NO_TAG("TLS connection too long", test_connection_too_long_tls),
	TEST_NO_TAG("TLS connection to TCP server", test_tls_to_tcp),
	TEST_NO_TAG("Register with DNS SRV failover TCP", register_dns_srv_tcp),
	TEST_NO_TAG("Register with DNS SRV failover TLS", register_dns_srv_tls),
	TEST_NO_TAG("Register with DNS SRV failover TLS with http proxy", register_dns_srv_tls_with_http_proxy),
	TEST_NO_TAG("Register with DNS load-balancing", register_dns_load_balancing),
jehan's avatar
jehan committed
1036 1037
	TEST_NO_TAG("Nonce reutilization", reuse_nonce),
	TEST_NO_TAG("Next Nonce", test_register_with_next_nonce)
Ghislain MARY's avatar
Ghislain MARY committed
1038 1039
};

1040
test_suite_t register_test_suite = {"Register", register_before_all, register_after_all, NULL,
Simon Morlat's avatar
Simon Morlat committed
1041
									NULL, sizeof(register_tests) / sizeof(register_tests[0]),
1042
									register_tests};