+ make sure parse_uri never returns NULL pointers - this
authorLuigi Rizzo <rizzo@icir.org>
Mon, 23 Oct 2006 15:45:36 +0000 (15:45 +0000)
committerLuigi Rizzo <rizzo@icir.org>
Mon, 23 Oct 2006 15:45:36 +0000 (15:45 +0000)
  simplifies its usage.

+ add another client for parse_uri, in handling Contact: strings
  (on passing, document the content of the "fullcontact" field);

+ in register_verify(), mark with XXX what i believe is another
  misinterpretation on the URI format when '@' is missing.
  No code changed here, so no fixes applied.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@45977 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c

index fb87cf7..4e8e1e8 100644 (file)
@@ -912,6 +912,7 @@ struct sip_pvt {
                AST_STRING_FIELD(cid_name);     /*!< Caller*ID name */
                AST_STRING_FIELD(via);          /*!< Via: header */
                AST_STRING_FIELD(fullcontact);  /*!< The Contact: that the UA registers with us */
+                       /* we only store the part in <brackets> in this field. */
                AST_STRING_FIELD(our_contact);  /*!< Our contact header */
                AST_STRING_FIELD(rpid);         /*!< Our RPID header */
                AST_STRING_FIELD(rpid_from);    /*!< Our RPID From header */
@@ -2242,7 +2243,7 @@ static char *get_in_brackets(char *tmp)
  * name:pass and domain:port.
  * It is safe to call with ret_name, pass, domain, port
  * pointing all to the same place.
- *
+ * Init pointers to empty string so we never get NULL dereferencing.
  * Overwrites the string.
  * return 0 on success, other values on error.
  */
@@ -2254,9 +2255,9 @@ static int parse_uri(char *uri, char *scheme,
 
        /* init field as required */
        if (*pass)
-               *pass = NULL;
+               *pass = "";
        if (*port)
-               *port = NULL;
+               *port = "";
        name = strsep(&uri, ";");       /* remove options */
        if (scheme) {
                int l = strlen(scheme);
@@ -2275,12 +2276,12 @@ static int parse_uri(char *uri, char *scheme,
                /* store the result in a temp. variable to avoid it being
                 * overwritten if arguments point to the same place.
                 */
-               char *c, *dom = NULL;
+               char *c, *dom = "";
 
                if ((c = strchr(name, '@')) == NULL) {
                        /* domain-only URI, according to the SIP RFC. */
                        dom = name;
-                       name = NULL;
+                       name = "";
                } else {
                        *c++ = '\0';
                        dom = c;
@@ -2289,7 +2290,7 @@ static int parse_uri(char *uri, char *scheme,
                        *c++ = '\0';
                        *port = c;
                }
-               if (name && pass && (c = strchr(name, ':'))) {  /* user:password */
+               if (pass && (c = strchr(name, ':'))) {  /* user:password */
                        *c++ = '\0';
                        *pass = c;
                }
@@ -2298,7 +2299,7 @@ static int parse_uri(char *uri, char *scheme,
        if (ret_name)   /* same as for domain, store the result only at the end */
                *ret_name = name;
        if (options)
-               *options = uri;
+               *options = uri ? uri : "";
 
        return error;
 }
@@ -7590,7 +7591,7 @@ static int set_address_from_contact(struct sip_pvt *pvt)
        struct hostent *hp;
        struct ast_hostent ahp;
        int port;
-       char *c, *host, *pt;
+       char *host, *pt;
        char *contact;
 
 
@@ -7604,32 +7605,12 @@ static int set_address_from_contact(struct sip_pvt *pvt)
 
        /* Work on a copy */
        contact = ast_strdupa(pvt->fullcontact);
+       /* We have only the part in <brackets> here so we just need to parse a SIP URI.*/
 
-       /* XXX this code is repeated all over */
-       /* Make sure it's a SIP URL */
-       if (strncasecmp(contact, "sip:", 4)) {
+       if (parse_uri(contact, "sip:", &contact, NULL, &host, &pt, NULL))
                ast_log(LOG_NOTICE, "'%s' is not a valid SIP contact (missing sip:) trying to use anyway\n", contact);
-       } else
-               contact += 4;
-
-       /* Ditch arguments */
-       /* XXX this code is replicated also shortly below */
-       contact = strsep(&contact, ";");        /* trim ; and beyond */
-
-       /* Grab host */
-       host = strchr(contact, '@');
-       if (!host) {    /* No username part */
-               host = contact;
-               c = NULL;
-       } else {
-               *host++ = '\0';
-       }
-       pt = strchr(host, ':');
-       if (pt) {
-               *pt++ = '\0';
-               port = atoi(pt);
-       } else
-               port = STANDARD_SIP_PORT;
+       port = !ast_strlen_zero(pt) ? atoi(pt) : STANDARD_SIP_PORT;
+       ast_verbose("--- set_address_from_contact host '%s'\n", host);
 
        /* XXX This could block for a long time XXX */
        /* We should only do this if it's a name, not an IP */
@@ -8193,6 +8174,9 @@ static enum check_auth_result register_verify(struct sip_pvt *p, struct sockaddr
                ast_log(LOG_NOTICE, "Invalid to address: '%s' from %s (missing sip:) trying to use anyway...\n", c, ast_inet_ntoa(sin->sin_addr));
        }
 
+       /* XXX here too we interpret a missing @domain as a name-only
+        * URI, whereas the RFC says this is a domain-only uri.
+        */
        /* Strip off the domain name */
        if ((c = strchr(name, '@'))) {
                *c++ = '\0';
@@ -9233,7 +9217,7 @@ static enum check_auth_result check_user_full(struct sip_pvt *p, struct sip_requ
        if (parse_uri(of, "sip:", &of, &dummy, &domain, &dummy, &dummy)) {
                ast_log(LOG_NOTICE, "From address missing 'sip:', using it anyway\n");
        }
-       if (of == NULL) {
+       if (ast_strlen_zero(of)) {
                /* XXX note: the original code considered a missing @host
                 * as a username-only URI. The SIP RFC (19.1.1) says that
                 * this is wrong, and it should be considered as a domain-only URI.