From ba2b99a6354298003f947da8c066c282e65b1631 Mon Sep 17 00:00:00 2001 From: Thomas Ries Date: Thu, 29 Jan 2004 20:11:12 +0000 Subject: [PATCH] - new doc/RFC3261_compliance.txt and comments in the code that refer to the RFC. --- ChangeLog | 2 + doc/RFC3261_compliance.txt | 59 +++++++++++++++ src/proxy.c | 150 ++++++++++++++++++++++++++++--------- src/register.c | 7 +- src/siproxd.c | 57 ++++++++++++-- 5 files changed, 228 insertions(+), 47 deletions(-) create mode 100644 doc/RFC3261_compliance.txt diff --git a/ChangeLog b/ChangeLog index 178fcf7..cc57352 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 0.5.2 ===== + 29-Jan-2004: - new doc/RFC3261_compliance.txt and comments in the + code that refer to the RFC. 28-Jan-2004: - don't die on INVITE requests that include no Contact header - which is legal. (patch by Robert Högberg) - RTP proxy: don't try to forward empty RTP packets diff --git a/doc/RFC3261_compliance.txt b/doc/RFC3261_compliance.txt new file mode 100644 index 0000000..0996489 --- /dev/null +++ b/doc/RFC3261_compliance.txt @@ -0,0 +1,59 @@ +RFC3261 describes in detail for UAs and proxies how to behave. +This document tries to make the link between the RFC and the +code locations in siproxd where these actions are performed. + + + +Request Processing: implemented +=================== + Section 16.3: Request Validation + 1. Reasonable Syntax yes + 2. URI scheme no + 3. Max-Forwards no + 4. (Optional) Loop Detection partially + 5. Proxy-Require no + 6. Proxy-Authorization yes + + Section 16.4 Route Information Preprocessing yes + + Section 16.5 Determining Request Targets no + + Section 16.6 Request Forwarding + 1. Make a copy of the received request yes + 2. Update the Request-URI yes + 3. Update the Max-Forwards header field no + 4. Optionally add a Record-route header field value no + 5. Optionally add additional header fields no + 6. Postprocess routing information no + 7. Determine the next-hop address, port, and transport yes + 8. Add a Via header field value yes + 9. Add a Content-Length header field if necessary yes + 10. Forward the new request yes + 11. Set timer C no + +Response Processing: implemented +==================== + Section 16.3: Request Validation + 1. Reasonable Syntax yes + 2. URI scheme no + 3. Max-Forwards no + 4. (Optional) Loop Detection partially + 5. Proxy-Require no + 6. Proxy-Authorization yes + + Section 16.7 Response Processing n/a + + Section 16.11 Stateless Proxy partially + Response processing as described in Section 16.7 does + not apply to a proxy behaving statelessly. When a + response arrives at a stateless proxy, the proxy MUST + inspect the sent-by value in the first (topmost) Via + header field value. If that address matches the proxy, + (it equals a value this proxy has inserted into previous + requests) the proxy MUST remove that header field value + from the response and forward the result to the location + indicated in the next Via header field value. The proxy + MUST NOT add to, modify, or remove the message body. + Unless specified otherwise, the proxy MUST NOT remove any + other header field values. If the address does not match + the proxy, the message MUST be silently discarded. diff --git a/src/proxy.c b/src/proxy.c index 1cc3541..9526d7c 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -54,6 +54,28 @@ extern int sip_socket; /* sending SIP datagrams */ * RETURNS * STS_SUCCESS on success * STS_FAILURE on error + * + * RFC3261 + * Section 16.3: Proxy Behavior - Request Validation + * 1. Reasonable Syntax + * 2. URI scheme + * 3. Max-Forwards + * 4. (Optional) Loop Detection + * 5. Proxy-Require + * 6. Proxy-Authorization + * + * Section 16.6: Proxy Behavior - Request Forwarding + * 1. Make a copy of the received request + * 2. Update the Request-URI + * 3. Update the Max-Forwards header field + * 4. Optionally add a Record-route header field value + * 5. Optionally add additional header fields + * 6. Postprocess routing information + * 7. Determine the next-hop address, port, and transport + * 8. Add a Via header field value + * 9. Add a Content-Length header field if necessary + * 10. Forward the new request + * 11. Set timer C */ int proxy_request (osip_message_t *request) { int i; @@ -69,18 +91,47 @@ int proxy_request (osip_message_t *request) { DEBUGC(DBCLASS_PROXY,"proxy_request"); -/* check for VIA loop, if yes, discard the request */ - sts=check_vialoop(request); - if (sts == STS_TRUE) { - DEBUGC(DBCLASS_PROXY,"via loop detected, ignoring request"); - /* according to the SIP RFC we are supposed to return an 482 error */ - return STS_FAILURE; - } + /* + * RFC 3261, Section 16.6 step 1 + * Proxy Behavior - Request Forwarding - Make a copy + */ + /* nothing to do here, copy is ready in 'request'*/ + /* + * RFC 3261, Section 16.6 step 3 + * Proxy Behavior - Request Forwarding - Max-Forwards + * (if Max-Forward header exists, decrement by one, if it does not + * exist, add a new one with value SHOULD be 70) + */ + /* NOT IMPLEMENTED */ + + /* + * RFC 3261, Section 16.6 step 4 + * Proxy Behavior - Request Forwarding - Add a Record-route header + */ + /* NOT IMPLEMENTED (optional) */ + + /* + * RFC 3261, Section 16.6 step 5 + * Proxy Behavior - Request Forwarding - Add Additional Header Fields + */ + /* NOT IMPLEMENTED (optional) */ + + /* + * RFC 3261, Section 16.6 step 6 + * Proxy Behavior - Request Forwarding - Postprocess routing information + */ + /* NOT IMPLEMENTED */ + + + /* + * RFC 3261, Section 16.4 + * Proxy Behavior - Route Information Preprocessing + * (process Record-Route header) + */ /* * Check if I am listed at the topmost Route header (if any Route * header is existing at all). If so, remove it from the list. - * -> RFC3261 Section 16.4 */ if (request->routes && !osip_list_eol(request->routes, 0)) { struct in_addr addr1, addr2, addr3; @@ -216,19 +267,20 @@ int proxy_request (osip_message_t *request) { * from an external host to the internal masqueraded host */ case REQTYP_INCOMING: - sts = get_ip_by_host(urlmap[i].true_url->host, &sendto_addr); - if (sts == STS_FAILURE) { - DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve URI [%s]", - urlmap[i].true_url->host); - return STS_FAILURE; - } - - /* rewrite request URI to point to the real host */ + /* + * RFC 3261, Section 16.6 step 2 + * Proxy Behavior - Request Forwarding - Request-URI + * (rewrite request URI to point to the real host) + */ /* 'i' still holds the valid index into the URLMAP table */ if (check_rewrite_rq_uri(request)==STS_TRUE) { proxy_rewrite_request_uri(request, i); } + /* + * RFC 3261, Section 16.6 step 8 + * Proxy Behavior - Add a Via header field value + */ /* add my Via header line (inbound interface)*/ sts = sip_add_myvia(request, IF_INBOUND); if (sts == STS_FAILURE) { @@ -259,12 +311,12 @@ int proxy_request (osip_message_t *request) { * from the internal masqueraded host to an external host */ case REQTYP_OUTGOING: - sts = get_ip_by_host(url->host, &sendto_addr); - if (sts == STS_FAILURE) { - DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve URI [%s]", - url->host); - return STS_FAILURE; - } + /* + * RFC 3261, Section 16.6 step 2 + * Proxy Behavior - Request Forwarding - Request-URI + */ + /* nothing to do for an outgoing request */ + /* if it is addressed to myself, then it must be some request * method that I as a proxy do not support. Reject */ @@ -289,6 +341,10 @@ int proxy_request (osip_message_t *request) { /* rewrite Contact header to represent the masqued address */ sip_rewrite_contact(request, DIR_OUTGOING); + /* + * RFC 3261, Section 16.8 + * Proxy Behavior - Add a Via header field value + */ /* add my Via header line (outbound interface)*/ sts = sip_add_myvia(request, IF_OUTBOUND); if (sts == STS_FAILURE) { @@ -329,10 +385,12 @@ int proxy_request (osip_message_t *request) { return STS_FAILURE; } - /* - * check if we need to send to an outbound proxy - */ + /* + * RFC 3261, Section 16.6 step 7 + * Proxy Behavior - Determine Next-Hop Address + */ if ((type == REQTYP_OUTGOING) && (configuration.outbound_proxy_host)) { + /* I have an outbound proxy configured */ sts = get_ip_by_host(configuration.outbound_proxy_host, &sendto_addr); if (sts == STS_FAILURE) { DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve outbound " @@ -346,7 +404,14 @@ int proxy_request (osip_message_t *request) { port = 5060; } } else { - /* the host part already has been resolved above*/ + /* get the destination from the SIP URI */ + sts = get_ip_by_host(url->host, &sendto_addr); + if (sts == STS_FAILURE) { + DEBUGC(DBCLASS_PROXY, "proxy_request: cannot resolve URI [%s]", + url->host); + return STS_FAILURE; + } + if (url->port) { port=atoi(url->port); } else { @@ -354,6 +419,16 @@ int proxy_request (osip_message_t *request) { } } + /* + * RFC 3261, Section 16.6 step 9 + * Proxy Behavior - Add a Content-Length header field if necessary + */ + /* not necessary, already in message and we do not support TCP */ + + /* + * RFC 3261, Section 16.6 step 10 + * Proxy Behavior - Forward the new request + */ sts = osip_message_to_str(request, &buffer); if (sts != 0) { ERROR("proxy_request: osip_message_to_str failed"); @@ -362,6 +437,13 @@ int proxy_request (osip_message_t *request) { sipsock_send_udp(&sip_socket, sendto_addr, port, buffer, strlen(buffer), 1); osip_free (buffer); + + /* + * RFC 3261, Section 16.6 step 11 + * Proxy Behavior - Set timer C + */ + /* NOT IMPLEMENTED - does this really apply for stateless proxies? */ + return STS_SUCCESS; } @@ -387,16 +469,11 @@ int proxy_response (osip_message_t *response) { DEBUGC(DBCLASS_PROXY,"proxy_response"); - - /* check for VIA loop, if yes, discard the request */ - sts=check_vialoop(response); - if (sts == STS_TRUE) { - DEBUGC(DBCLASS_PROXY,"via loop detected, ignoring response"); - /* according to the SIP RFC we are supposed to return an 482 error */ - return STS_FAILURE; - } - - /* ALWAYS: remove my Via header line */ + /* + * RFC 3261, Section 16.11 + * Proxy Behavior - Remove my Via header field value + */ + /* remove my Via header line */ sts = sip_del_myvia(response); if (sts == STS_FAILURE) { DEBUGC(DBCLASS_PROXY,"not addressed to my VIA, ignoring response"); @@ -408,7 +485,6 @@ int proxy_response (osip_message_t *response) { * world to one of our registered clients */ - /* Ahhrghh...... a response seems to have NO contact information... * so let's take FROM instead... * the TO and FROM headers are EQUAL to the request - that means diff --git a/src/register.c b/src/register.c index 545593e..0125e4e 100644 --- a/src/register.c +++ b/src/register.c @@ -174,10 +174,13 @@ int register_client(osip_message_t *my_msg, int force_lcl_masq) { osip_header_t *expires_hdr; osip_uri_param_t *expires_param=NULL; - /* check for proxy authentication */ + /* + * RFC 3261, Section 16.3 step 6 + * Proxy Behavior - Request Validation - Proxy-Authorization + */ sts = authenticate_proxy(my_msg); if (sts == STS_FAILURE) { - /* failed */ + /* failed */ WARN("proxy authentication failed for %s@%s", (my_msg->to->url->username)? my_msg->to->url->username : "*NULL*", my_msg->to->url->host); diff --git a/src/siproxd.c b/src/siproxd.c index 66bb2ed..51292c1 100644 --- a/src/siproxd.c +++ b/src/siproxd.c @@ -256,15 +256,19 @@ int main (int argc, char *argv[]) sts=security_check_raw(buff, i); if (sts != STS_SUCCESS) continue; /* there are no resources to free */ - /* parse the received message */ + /* init sip_msg */ sts=osip_message_init(&my_msg); my_msg->message=NULL; - if (sts != 0) { ERROR("osip_message_init() failed... this is not good"); continue; /* skip, there are no resources to free */ } + /* + * RFC 3261, Section 16.3 step 1 + * Proxy Behavior - Request Validation - Reasonable Syntax + * (parse the received message) + */ sts=osip_message_parse(my_msg, buff); if (sts != 0) { ERROR("osip_message_parse() failed... this is not good"); @@ -280,19 +284,56 @@ int main (int argc, char *argv[]) goto end_loop; /* skip and free resources */ } + /* + * RFC 3261, Section 16.3 step 2 + * Proxy Behavior - Request Validation - URI scheme + * (check request URI and refuse with 416 if not understood) + */ + /* NOT IMPLEMENTED */ + + /* + * RFC 3261, Section 16.3 step 3 + * Proxy Behavior - Request Validation - Max-Forwards check + * (check Max-Forward header and refuse with 483 if too many hops) + */ + /* NOT IMPLEMENTED */ + + /* + * RFC 3261, Section 16.3 step 4 + * Proxy Behavior - Request Validation - Loop Detection check + * (check for loop and return 482 if a loop is detected) + */ + if (check_vialoop(my_msg) == STS_TRUE) { + DEBUGC(DBCLASS_PROXY,"via loop detected, ignoring request"); + /* we should return 482, NOT IMPLEMENTED */ + goto end_loop; /* skip and free resources */ + } + + /* + * RFC 3261, Section 16.3 step 5 + * Proxy Behavior - Request Validation - Proxy-Require check + * (check Proxy-Require header and return 420 if unsupported option) + */ + /* NOT IMPLEMENTED */ + + /* + * RFC 3261, Section 16.5 + * Proxy Behavior - Determining Request Targets + */ + /* NOT IMPLEMENTED */ + DEBUGC(DBCLASS_SIP,"received SIP type %s:%s", (MSG_IS_REQUEST(my_msg))? "REQ" : "RES", (MSG_IS_REQUEST(my_msg) ? ((my_msg->sip_method)? my_msg->sip_method : "NULL") : ((my_msg->reason_phrase) ? my_msg->reason_phrase : "NULL"))); - /* - * if an REQ REGISTER, check if it is directed to myself, - * or am I just the outbound proxy but no registrar. - * - If I'm the registrar, register & generate answer - * - If I'm just the outbound proxy, register, rewrite & forward - */ + * if an REQ REGISTER, check if it is directed to myself, + * or am I just the outbound proxy but no registrar. + * - If I'm the registrar, register & generate answer + * - If I'm just the outbound proxy, register, rewrite & forward + */ if (MSG_IS_REGISTER(my_msg) && MSG_IS_REQUEST(my_msg)) { if (access & ACCESSCTL_REG) { osip_uri_t *url;