Index: /pjproject/trunk/pjsip/include/pjsip/sip_config.h
===================================================================
--- /pjproject/trunk/pjsip/include/pjsip/sip_config.h	(revision 4898)
+++ /pjproject/trunk/pjsip/include/pjsip/sip_config.h	(revision 4899)
@@ -146,4 +146,16 @@
 	pj_bool_t resolve_hostname_to_get_interface;
 
+	/**
+	 * Disable security check on incoming messages in a secure dialog.
+	 * A secure dialog is created when the request that creates the dialog
+	 * uses "sips" scheme in its request URI. Contact URI should use "sips"
+	 * scheme and the top-most Record-Route URI, if any, should use either
+	 * "sips" scheme or "transport=tls" param. See also
+	 * https://trac.pjsip.org/repos/ticket/1735.
+	 *
+	 * Default is PJ_FALSE.
+	 */
+	pj_bool_t disable_secure_dlg_check;
+
     } endpt;
 
Index: /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 4898)
+++ /pjproject/trunk/pjsip/src/pjsip-ua/sip_inv.c	(revision 4899)
@@ -116,4 +116,7 @@
 				         pj_bool_t end_sess_on_failure);
 
+static pj_bool_t inv_check_secure_dlg(pjsip_inv_session *inv,
+				      pjsip_event *e);
+
 static void (*inv_state_handler[])( pjsip_inv_session *inv, pjsip_event *e) = 
 {
@@ -991,4 +994,47 @@
 	status = PJSIP_ERRNO_FROM_SIP_STATUS(code);
 	goto on_return;
+    }
+
+    /* Ticket #1735: Check Contact/Record-Route header in a secure dialog. */
+    if (pjsip_cfg()->endpt.disable_secure_dlg_check == PJ_FALSE &&
+	msg && c_hdr && c_hdr->uri)
+    {
+	/* Check Contact header */
+	if (!PJSIP_URI_SCHEME_IS_SIPS(c_hdr->uri))
+	    status = PJSIP_ESESSIONINSECURE;
+
+	/* Check top Record-Route header */
+	if (status == PJ_SUCCESS) {
+	    pjsip_rr_hdr *r = (pjsip_rr_hdr*)
+			      pjsip_msg_find_hdr(msg, PJSIP_H_RECORD_ROUTE,
+						 NULL);
+	    if (r && !PJSIP_URI_SCHEME_IS_SIPS(&r->name_addr)) {
+		/* Not "sips", check if it is "sip" and has param
+		 * "transport=tls".
+		 */
+		if (PJSIP_URI_SCHEME_IS_SIP(&r->name_addr)) {
+		    pjsip_sip_uri *sip_uri = (pjsip_sip_uri*)
+				     pjsip_uri_get_uri(r->name_addr.uri);
+		    if (pj_stricmp2(&sip_uri->transport_param, "tls")!=0)
+			status = PJSIP_ESESSIONINSECURE;
+		} else {
+		    /* Not "sips" nor "sip", treat it as insecure? */
+		    status = PJSIP_ESESSIONINSECURE;
+		}
+	    }
+	}
+
+	if (status != PJ_SUCCESS) {
+	    pjsip_warning_hdr *w;
+	    pj_str_t warn_text = pj_str("SIPS Required");
+	    w = pjsip_warning_hdr_create(tmp_pool, 381,
+					 pjsip_endpt_name(endpt),
+					 &warn_text);
+	    if (w) {
+		pj_list_push_back(&res_hdr_list, w);
+	    }
+	    code = PJSIP_SC_TEMPORARILY_UNAVAILABLE;
+	    goto on_return;
+	}
     }
 
@@ -3225,10 +3271,19 @@
  */
 static void inv_respond_incoming_update(pjsip_inv_session *inv,
-					pjsip_rx_data *rdata)
+					pjsip_event *e)
 {
     pjmedia_sdp_neg_state neg_state;
     pj_status_t status;
     pjsip_tx_data *tdata = NULL;
+    pjsip_rx_data *rdata;
     pjsip_status_code st_code;
+
+    pj_assert(e->type == PJSIP_EVENT_TSX_STATE &&
+	      e->body.tsx_state.type == PJSIP_EVENT_RX_MSG);
+    rdata = e->body.tsx_state.src.rdata;
+
+    /* Check routing URI scheme for secure dialog */
+    if (!inv_check_secure_dlg(inv, e))
+	return;
 
     /* Invoke Session Timers module */
@@ -3386,19 +3441,25 @@
     {
 	pjsip_rx_data *rdata = e->body.tsx_state.src.rdata;
-	status = handle_timer_response(inv, rdata, PJ_FALSE);
-
-	if (rdata->msg_info.msg->body) {
-	    /* Only process remote SDP if we have sent local offer */
-	    if (inv->neg && pjmedia_sdp_neg_get_state(inv->neg) == 
-					PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER)
-	    {
-		status = inv_check_sdp_in_incoming_msg(inv, tsx, rdata);
-	    } else {
-		PJ_LOG(5,(THIS_FILE, "Ignored message body in %s as no local "
-				     "offer was sent",
-				     pjsip_rx_data_get_info(rdata)));
+
+	/* Check routing URI scheme for secure dialog */
+	if (inv_check_secure_dlg(inv, e)) {
+
+	    status = handle_timer_response(inv, rdata, PJ_FALSE);
+
+	    if (rdata->msg_info.msg->body) {
+		/* Only process remote SDP if we have sent local offer */
+		if (inv->neg && pjmedia_sdp_neg_get_state(inv->neg) == 
+					    PJMEDIA_SDP_NEG_STATE_LOCAL_OFFER)
+		{
+		    status = inv_check_sdp_in_incoming_msg(inv, tsx, rdata);
+		} else {
+		    PJ_LOG(5,(THIS_FILE, "Ignored message body in %s as no "
+					 "local offer was sent",
+					 pjsip_rx_data_get_info(rdata)));
+		}
 	    }
 	}
-	handled = PJ_TRUE;
+
+        handled = PJ_TRUE;
     }
 
@@ -3515,4 +3576,112 @@
     }
 }
+
+
+/* Ticket #1735: If this is a secure dialog, make sure that any incoming
+ * initial/subsequent INVITE/UPDATE request or the 2xx response to INVITE/
+ * UPDATE specifies secure Contact and Record-Route headers.
+ */
+static pj_bool_t inv_check_secure_dlg(pjsip_inv_session *inv,
+				      pjsip_event *e)
+{
+    pjsip_transaction *tsx = e->body.tsx_state.tsx;
+    pjsip_dialog *dlg = pjsip_tsx_get_dlg(tsx);
+
+    if (pjsip_cfg()->endpt.disable_secure_dlg_check == PJ_FALSE &&
+	dlg->secure && e->body.tsx_state.type==PJSIP_EVENT_RX_MSG &&
+	(tsx->role==PJSIP_ROLE_UAC && tsx->status_code/100 == 2 ||
+	 tsx->role==PJSIP_ROLE_UAS && tsx->state == PJSIP_TSX_STATE_TRYING) &&
+	(tsx->method.id==PJSIP_INVITE_METHOD || 
+	 pjsip_method_cmp(&tsx->method, &pjsip_update_method)==0))
+    {
+	const pjsip_msg *msg = e->body.tsx_state.src.rdata->msg_info.msg;
+	pj_status_t status = PJ_SUCCESS;
+	pjsip_contact_hdr *c;
+
+	/* Check Contact header */
+	c = (pjsip_contact_hdr*)
+	    pjsip_msg_find_hdr(msg,PJSIP_H_CONTACT, NULL);
+	if (!(c && c->uri && PJSIP_URI_SCHEME_IS_SIPS(c->uri)))
+	    status = PJSIP_ESESSIONINSECURE;
+
+	/* Check top Record-Route header */
+	if (status == PJ_SUCCESS) {
+	    pjsip_rr_hdr *r = (pjsip_rr_hdr*)
+			      pjsip_msg_find_hdr(msg, PJSIP_H_RECORD_ROUTE,
+						 NULL);
+	    if (r && !PJSIP_URI_SCHEME_IS_SIPS(&r->name_addr)) {
+		/* Not "sips", check if it is "sip" and has param
+		 * "transport=tls".
+		 */
+		if (PJSIP_URI_SCHEME_IS_SIP(&r->name_addr)) {
+		    pjsip_sip_uri *sip_uri = (pjsip_sip_uri*)
+				     pjsip_uri_get_uri(r->name_addr.uri);
+		    if (pj_stricmp2(&sip_uri->transport_param, "tls")!=0)
+			status = PJSIP_ESESSIONINSECURE;
+		} else {
+		    /* Not "sips" nor "sip", treat it as insecure? */
+		    status = PJSIP_ESESSIONINSECURE;
+		}
+	    }
+	}
+
+	if (status == PJSIP_ESESSIONINSECURE) {
+	    /* Found non-SIPS scheme in Contact/Record-Route header */
+
+	    pj_str_t warn_text = pj_str("SIPS Required");
+
+	    if (tsx->role == PJSIP_ROLE_UAC) {
+
+		/* If we are UAC, terminate the session */
+		pjsip_tx_data *bye;
+
+		PJ_LOG(4,(inv->obj_name,
+			  "Secure dialog requires SIPS scheme in Contact and "
+			  "Record-Route headers, ending the session"));
+
+		status = pjsip_inv_end_session(inv, 480, NULL, &bye);
+		if (status == PJ_SUCCESS && bye) {
+		    pjsip_warning_hdr *w;
+		    w = pjsip_warning_hdr_create(bye->pool, 381,
+						 pjsip_endpt_name(dlg->endpt),
+						 &warn_text);
+		    if (w)
+			pjsip_msg_add_hdr(bye->msg, (pjsip_hdr*)w);
+
+		    status = pjsip_inv_send_msg(inv, bye);
+		}
+
+	    } else {
+
+		/* If we are UAS, reject the request */
+		pjsip_rx_data *rdata = e->body.tsx_state.src.rdata;
+		pjsip_tx_data *tdata;
+
+		PJ_LOG(4,(inv->obj_name,
+			  "Secure dialog requires SIPS scheme in Contact and "
+			  "Route headers, rejecting the request"));
+
+		status = pjsip_dlg_create_response(inv->dlg, rdata, 480,
+						   NULL, &tdata);
+		if (status == PJ_SUCCESS) {
+		    pjsip_warning_hdr *w;
+		    w = pjsip_warning_hdr_create(tdata->pool, 381,
+						 pjsip_endpt_name(dlg->endpt),
+						 &warn_text);
+		    if (w)
+			pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)w);
+
+		    pjsip_dlg_send_response(dlg, tsx, tdata);
+		}
+
+	    }
+
+    	    return PJ_FALSE;
+	}
+    }
+
+    return PJ_TRUE;
+}
+
 
 
@@ -3866,4 +4035,10 @@
 		pj_assert(0);
 
+		inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e);
+
+		/* Check routing URI scheme for secure dialog */
+		if (!inv_check_secure_dlg(inv, e))
+		    break;
+
 		/* Process session timer response. */
 		status = handle_timer_response(inv,
@@ -3873,6 +4048,4 @@
 		    break;
 
-		inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e);
-    
 		inv_check_sdp_in_incoming_msg(inv, tsx, 
 					      e->body.tsx_state.src.rdata);
@@ -3890,4 +4063,12 @@
 	    if (tsx->status_code/100 == 2) {
 		/* This must be receipt of 2xx response */
+		pj_assert(e->body.tsx_state.type == PJSIP_EVENT_RX_MSG);
+
+		/* Set state to CONNECTING */
+		inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e);
+
+		/* Check routing URI scheme for secure dialog */
+		if (!inv_check_secure_dlg(inv, e))
+		    break;
 
 		/* Process session timer response. */
@@ -3898,13 +4079,7 @@
 		    break;
 
-		/* Set state to CONNECTING */
-		inv_set_state(inv, PJSIP_INV_STATE_CONNECTING, e);
-
 		inv_check_sdp_in_incoming_msg(inv, tsx, 
 					      e->body.tsx_state.src.rdata);
-
 		/* Send ACK */
-		pj_assert(e->body.tsx_state.type == PJSIP_EVENT_RX_MSG);
-
 		inv_send_ack(inv, e);
 
@@ -3943,5 +4118,5 @@
 	 * Handle a very early UPDATE
 	 */
-	inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata);
+	inv_respond_incoming_update(inv, e);
 
 
@@ -4061,4 +4236,8 @@
 		    pj_status_t status;
 
+		    /* Check routing URI scheme for secure dialog */
+		    if (!inv_check_secure_dlg(inv, e))
+			break;
+
 		    /* Process session timer response. */
 		    status = handle_timer_response(inv, 
@@ -4101,4 +4280,8 @@
 		    pj_status_t status;
 		    
+		    /* Check routing URI scheme for secure dialog */
+		    if (!inv_check_secure_dlg(inv, e))
+			break;
+
 		    /* Process session timer response. */
 		    status = handle_timer_response(inv, 
@@ -4150,5 +4333,5 @@
 	 * Handle incoming UPDATE
 	 */
-	inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata);
+	inv_respond_incoming_update(inv, e);
 
 
@@ -4358,5 +4541,5 @@
 	 * Handle incoming UPDATE
 	 */
-	inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata);
+	inv_respond_incoming_update(inv, e);
 
 
@@ -4487,4 +4670,8 @@
 		return;
 	    }
+
+	    /* Check routing URI scheme for secure dialog */
+	    if (!inv_check_secure_dlg(inv, e))
+		return;
 
 	    /* Save the invite transaction. */
@@ -4730,4 +4917,8 @@
 	    /* Re-INVITE was accepted. */
 
+	    /* Check routing URI scheme for secure dialog */
+	    if (!inv_check_secure_dlg(inv, e))
+		return;
+
 	    /* Process session timer response. */
 	    status = handle_timer_response(inv, 
@@ -4788,5 +4979,5 @@
 	 * Handle incoming UPDATE
 	 */
-	inv_respond_incoming_update(inv, e->body.tsx_state.src.rdata);
+	inv_respond_incoming_update(inv, e);
 
     } else if (tsx->role == PJSIP_ROLE_UAC &&
Index: /pjproject/trunk/pjsip/src/pjsip/sip_config.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_config.c	(revision 4898)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_config.c	(revision 4899)
@@ -34,5 +34,6 @@
        PJSIP_FOLLOW_EARLY_MEDIA_FORK,
        PJSIP_REQ_HAS_VIA_ALIAS,
-       PJSIP_RESOLVE_HOSTNAME_TO_GET_INTERFACE
+       PJSIP_RESOLVE_HOSTNAME_TO_GET_INTERFACE,
+       0
     },
 
