]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
ext_kerberos_ldap_group: Memory Leaks
authorAmos Jeffries <squid3@treenet.co.nz>
Sat, 17 Nov 2012 12:31:44 +0000 (05:31 -0700)
committerAmos Jeffries <squid3@treenet.co.nz>
Sat, 17 Nov 2012 12:31:44 +0000 (05:31 -0700)
* Allocate sufficient memory to nul-terminate the cleaned input buffer
  on worst-case input obfuscation level.

* Free temporary parsing buffers, and parsed group structures when parse
  aborts on failure.

* Remove several useless if() conditionals for simpler code flow:
 - Squid xfree() handles NULL pointers.
 - Squid safe_free() handles NULL pointers and assigns NULL after freeing
 - assigning x->next from local NULL pointer is okay.

 Detected by Coverity Scan. Issues 743377, 743378, 740412, 740417, 740418
   740419, 740420, 740421, 740448, 740458, 740342, 740422, 740449, 740450
   740423, 740424.

helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc
helpers/external_acl/kerberos_ldap_group/support_group.cc
helpers/external_acl/kerberos_ldap_group/support_ldap.cc
helpers/external_acl/kerberos_ldap_group/support_lserver.cc
helpers/external_acl/kerberos_ldap_group/support_netbios.cc

index 3117bf3e3d345428ae13392fcb3c8a40631d98e8..464b6732352b23d1d371ad629d3fe4957981a990 100644 (file)
@@ -231,7 +231,7 @@ main(int argc, char *const argv[])
     char *up=NULL, *dp=NULL, *np=NULL;
     char *nuser, *nuser8 = NULL, *netbios;
     char *c;
-    int opt,gopt;
+    int opt;
     struct main_args margs;
 
     setbuf(stdout, NULL);
@@ -336,8 +336,8 @@ main(int argc, char *const argv[])
     }
 
     debug((char *) "%s| %s: INFO: Starting version %s\n", LogTime(), PROGRAM, KERBEROS_LDAP_GROUP_VERSION);
+    int gopt = 0;
     if (create_gd(&margs)) {
-        gopt = 0;
         if ( margs.glist != NULL ) {
             debug((char *) "%s| %s: FATAL: Error in group list: %s\n", LogTime(), PROGRAM, margs.glist ? margs.glist : "NULL");
             SEND_ERR("");
@@ -441,9 +441,9 @@ main(int argc, char *const argv[])
             clean_args(&margs);
             exit(-1);
         }
-        if ( gopt && user ) {
+        if (gopt) {
             if ((group = strtok(NULL, " \n")) != NULL) {
-                debug((char *) "%s| %s: INFO: Read group list %s from stdin\n", LogTime(), PROGRAM,group);
+                debug((char *) "%s| %s: INFO: Read group list %s from stdin\n", LogTime(), PROGRAM, group);
                 rfc1738_unescape(group);
                 if (margs.groups) {
                     clean_gd(margs.groups);
index f6f0868960eb319ceff3e8f55e247e38da9aafee..a43c59e7127f7dd58bc46eb1fbc237dbe158f006 100644 (file)
@@ -42,6 +42,17 @@ init_gd(void) {
     return gdsp;
 }
 
+void
+free_gd(struct gdstruct *gdsp) {
+    while(gdsp) {
+        struct gdstruct *gdspn = gdsp->next;
+        xfree(gdsp->group);
+        xfree(gdsp->domain);
+        xfree(gdsp);
+        gdsp = gdspn;
+    }
+}
+
 char *utf8dup(struct main_args *margs);
 
 char *
@@ -101,35 +112,24 @@ char *hex_utf_char(struct main_args *margs, int flag);
 char *
 hex_utf_char(struct main_args *margs, int flag)
 {
-    char *up;
-    char *upd;
-    char *ul;
-    int a, n, nl, ival, ichar;
+    int ival, ichar;
     int iUTF2, iUTF3, iUTF4;
 
-    if (flag) {
-        up = margs->ulist;
-    } else {
-        up = margs->tlist;
-    }
-
+    char *up = (flag ? margs->ulist : margs->tlist);
     if (!up)
         return NULL;
 
-    upd = strrchr(up, '@');
-    if (upd)
-        a = upd - up;
-    else
-        a = strlen(up);
+    char *upd = strrchr(up, '@');
+    size_t a = (upd ? (upd - up) : strlen(up) );
 
-    ul = (char *) xmalloc(strlen(up));
-    n = 0;
-    nl = 0;
+    char *ul = (char *) xmalloc(strlen(up)+1);
+    size_t n = 0;
+    int nl = 0;
     iUTF2 = 0;
     iUTF3 = 0;
     iUTF4 = 0;
 
-    while (n < (int) strlen(up)) {
+    while (n < strlen(up)) {
         if (flag && n == a)
             break;
         if (up[n] == '@') {
@@ -286,8 +286,7 @@ hex_utf_char(struct main_args *margs, int flag)
     if (iUTF2 || iUTF3 || iUTF4) {
         debug((char *) "%s| %s: INFO: iUTF2: %d iUTF3: %d iUTF4: %d\n", LogTime(), PROGRAM, iUTF2, iUTF3, iUTF4);
         debug((char *) "%s| %s: WARNING: Invalid UTF-8 sequence for Unicode %s\n", LogTime(), PROGRAM, ul);
-        if (ul)
-            xfree(ul);
+        xfree(ul);
         return NULL;
     }
     if (flag && upd)
@@ -299,7 +298,6 @@ int
 create_gd(struct main_args *margs)
 {
     char *gp, *dp;
-    char *hp1, *hp2, *up;
     char *p;
     struct gdstruct *gdsp = NULL, *gdspn = NULL;
     /*
@@ -321,28 +319,38 @@ create_gd(struct main_args *margs)
      *
      *
      */
-    hp1 = hex_utf_char(margs, 0);
-    hp2 = hex_utf_char(margs, 1);
-    up = utf8dup(margs);
+    char *hp1 = hex_utf_char(margs, 0);
+    char *hp2 = hex_utf_char(margs, 1);
+    char *up = utf8dup(margs);
+    char *gpbuf = NULL;
+
+    // release the allocated UTF decoding buffers
+#define cleanup() { \
+    xfree(gpbuf); \
+    xfree(hp1); \
+    xfree(hp2); \
+    free_gd(gdsp); \
+ }
+
     p = up;
     if (hp1) {
         if (hp2) {
             if (up) {
-                p = (char *) xmalloc(strlen(up) + strlen(hp1) + strlen(hp2) + 2);
+                gpbuf = p = (char *) xmalloc(strlen(up) + strlen(hp1) + strlen(hp2) + 2);
                 strcpy(p, up);
                 strcat(p, ":");
                 strcat(p, hp1);
                 strcat(p, ":");
                 strcat(p, hp2);
             } else {
-                p = (char *) xmalloc(strlen(hp1) + strlen(hp2) + 1);
+                gpbuf = p = (char *) xmalloc(strlen(hp1) + strlen(hp2) + 1);
                 strcpy(p, hp1);
                 strcat(p, ":");
                 strcat(p, hp2);
             }
         } else {
             if (up) {
-                p = (char *) xmalloc(strlen(up) + strlen(hp1) + 1);
+                gpbuf = p = (char *) xmalloc(strlen(up) + strlen(hp1) + 1);
                 strcpy(p, up);
                 strcat(p, ":");
                 strcat(p, hp1);
@@ -352,7 +360,7 @@ create_gd(struct main_args *margs)
     } else {
         if (hp2) {
             if (up) {
-                p = (char *) xmalloc(strlen(up) + strlen(hp2) + 1);
+                gpbuf = p = (char *) xmalloc(strlen(up) + strlen(hp2) + 1);
                 strcpy(p, up);
                 strcat(p, ":");
                 strcat(p, hp2);
@@ -367,6 +375,7 @@ create_gd(struct main_args *margs)
 
     if (!p) {
         debug((char *) "%s| %s: ERROR: No groups defined.\n", LogTime(), PROGRAM);
+        cleanup();
         return (1);
     }
     while (*p) {               /* loop over group list */
@@ -377,18 +386,19 @@ create_gd(struct main_args *margs)
         if (*p == '@') {       /* end of group name - start of domain name */
             if (p == gp) {     /* empty group name not allowed */
                 debug((char *) "%s| %s: ERROR: No group defined for domain %s\n", LogTime(), PROGRAM, p);
+                cleanup();
                 return (1);
             }
             *p = '\0';
             ++p;
             gdsp = init_gd();
-            gdsp->group = gp;
-            if (gdspn)         /* Have already an existing structure */
-                gdsp->next = gdspn;
+            gdsp->group = xstrdup(gp);
+            gdsp->next = gdspn;
             dp = p;            /* after @ starts new domain name */
         } else if (*p == ':') {        /* end of group name or end of domain name */
             if (p == gp) {     /* empty group name not allowed */
                 debug((char *) "%s| %s: ERROR: No group defined for domain %s\n", LogTime(), PROGRAM, p);
+                cleanup();
                 return (1);
             }
             *p = '\0';
@@ -398,9 +408,8 @@ create_gd(struct main_args *margs)
                 dp = NULL;
             } else {           /* end of group name and no domain name */
                 gdsp = init_gd();
-                gdsp->group = gp;
-                if (gdspn)     /* Have already an existing structure */
-                    gdsp->next = gdspn;
+                gdsp->group = xstrdup(gp);
+                gdsp->next = gdspn;
             }
             gdspn = gdsp;
             gp = p;            /* after : starts new group name */
@@ -410,19 +419,22 @@ create_gd(struct main_args *margs)
     }
     if (p == gp) {             /* empty group name not allowed */
         debug((char *) "%s| %s: ERROR: No group defined for domain %s\n", LogTime(), PROGRAM, p);
+        cleanup();
         return (1);
     }
     if (dp) {                  /* end of domain name */
         gdsp->domain = xstrdup(dp);
     } else {                   /* end of group name and no domain name */
         gdsp = init_gd();
-        gdsp->group = gp;
+        gdsp->group = xstrdup(gp);
         if (gdspn)             /* Have already an existing structure */
             gdsp->next = gdspn;
     }
     debug((char *) "%s| %s: INFO: Group %s  Domain %s\n", LogTime(), PROGRAM, gdsp->group, gdsp->domain ? gdsp->domain : "NULL");
 
     margs->groups = gdsp;
+    gdsp = NULL; // prevent the cleanup() deallocating it.
+    cleanup();
     return (0);
 }
 #endif
index a6b058bf9b0793690bf09574eac04709350a4f82..08ac11ba7ec1c87fd82981f983d1f168f13c41d5 100644 (file)
@@ -369,19 +369,18 @@ search_group_tree(struct main_args *margs, LDAP * ld, char *bindp, char *ldap_gr
     search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
     snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
 
-    if (ldap_filter_esc)
-        xfree(ldap_filter_esc);
+    xfree(ldap_filter_esc);
 
     if (depth > margs->mdepth) {
         debug((char *) "%s| %s: DEBUG: Max search depth reached %d>%d\n", LogTime(), PROGRAM, depth, margs->mdepth);
+        xfree(search_exp);
         return 0;
     }
     debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM, bindp, search_exp);
     rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
                            search_exp, NULL, 0,
                            NULL, NULL, &searchtime, 0, &res);
-    if (search_exp)
-        xfree(search_exp);
+    xfree(search_exp);
 
     if (rc != LDAP_SUCCESS) {
         error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
@@ -744,22 +743,16 @@ tool_ldap_open(struct main_args * margs, char *host, int port, char *ssl)
             rc = ldap_url_parse(ldapuri, &url);
             if (rc != LDAP_SUCCESS) {
                 error((char *) "%s| %s: ERROR: Error while parsing url: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
-                if (ldapuri)
-                    xfree(ldapuri);
-                if (url)
-                    xfree(url);
+                xfree(ldapuri);
+                xfree(url);
                 return NULL;
             }
 #else
 #error "No URL parsing function"
 #endif
-            if (url) {
-                xfree(url);
-                url = NULL;
-            }
+            safe_free(url);
             rc = ldap_initialize(&ld, ldapuri);
-            if (ldapuri)
-                xfree(ldapuri);
+            xfree(ldapuri);
             if (rc != LDAP_SUCCESS) {
                 error((char *) "%s| %s: ERROR: Error while initialising connection to ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
                 ldap_unbind(ld);
@@ -897,7 +890,7 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
                 continue;
             }
             lcreds = (ldap_creds *) xmalloc(sizeof(struct ldap_creds));
-            lcreds->dn = bindp ? xstrdup(bindp) : NULL;
+            lcreds->dn = NULL;
             lcreds->pw = margs->ssl ? xstrdup(margs->ssl) : NULL;
             ldap_set_rebind_proc(ld, ldap_sasl_rebind, (char *) lcreds);
             if (ld != NULL) {
@@ -938,9 +931,7 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
             port = atoi(p);
         }
         nhosts = get_hostname_list(margs, &hlist, 0, host);
-        if (host)
-            xfree(host);
-        host = NULL;
+        safe_free(host);
         for (i = 0; i < nhosts; ++i) {
 
             ld = tool_ldap_open(margs, hlist[i].host, port, ssl);
@@ -967,8 +958,7 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
 
         }
         nhosts = free_hostname_list(&hlist, nhosts);
-        if (bindp)
-            xfree(bindp);
+        xfree(bindp);
         if (margs->lbind) {
             bindp = xstrdup(margs->lbind);
         } else {
@@ -1005,15 +995,13 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
     search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
     snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
 
-    if (ldap_filter_esc)
-        xfree(ldap_filter_esc);
+    xfree(ldap_filter_esc);
 
     debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter : %s\n", LogTime(), PROGRAM, bindp, search_exp);
     rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
                            search_exp, NULL, 0,
                            NULL, NULL, &searchtime, 0, &res);
-    if (search_exp)
-        xfree(search_exp);
+    xfree(search_exp);
 
     if (rc != LDAP_SUCCESS) {
         error((char *) "%s| %s: ERROR: Error searching ldap server: %s\n", LogTime(), PROGRAM, ldap_err2string(rc));
@@ -1121,15 +1109,13 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
         search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
         snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
 
-        if (ldap_filter_esc)
-            xfree(ldap_filter_esc);
+        xfree(ldap_filter_esc);
 
         debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, bindp, search_exp);
         rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
                                search_exp, NULL, 0,
                                NULL, NULL, &searchtime, 0, &res);
-        if (search_exp)
-            xfree(search_exp);
+        xfree(search_exp);
 
         debug((char *) "%s| %s: DEBUG: Found %d ldap entr%s\n", LogTime(), PROGRAM, ldap_count_entries(ld, res), ldap_count_entries(ld, res) > 1 || ldap_count_entries(ld, res) == 0 ? "ies" : "y");
 
@@ -1147,15 +1133,13 @@ get_memberof(struct main_args *margs, char *user, char *domain, char *group)
             search_exp = (char *) xmalloc(strlen(filter) + strlen(ldap_filter_esc) + 1);
             snprintf(search_exp, strlen(filter) + strlen(ldap_filter_esc) + 1, filter, ldap_filter_esc);
 
-            if (ldap_filter_esc)
-                xfree(ldap_filter_esc);
+            xfree(ldap_filter_esc);
 
             debug((char *) "%s| %s: DEBUG: Search ldap server with bind path %s and filter: %s\n", LogTime(), PROGRAM, bindp, search_exp);
             rc = ldap_search_ext_s(ld, bindp, LDAP_SCOPE_SUBTREE,
                                    search_exp, NULL, 0,
                                    NULL, NULL, &searchtime, 0, &res);
-            if (search_exp)
-                xfree(search_exp);
+            xfree(search_exp);
 
             max_attr_2 = get_attributes(margs, ld, res, ATTRIBUTE, &attr_value_2);
             /*
@@ -1212,16 +1196,11 @@ cleanup:
         krb5_cleanup();
 #endif
     if (lcreds) {
-        if (lcreds->dn)
-            xfree(lcreds->dn);
-        if (lcreds->pw)
-            xfree(lcreds->pw);
+        xfree(lcreds->dn);
+        xfree(lcreds->pw);
         xfree(lcreds);
     }
-    if (bindp)
-        xfree(bindp);
-    bindp = NULL;
+    xfree(bindp);
     return (retval);
-
 }
 #endif
index 16bb243d2ec566b54d30739ba5797fe04dc2bd7a..f232147889ea884f7d91d0a1579b5adb0c9ef2de 100644 (file)
@@ -40,6 +40,18 @@ init_ls(void) {
     return lssp;
 }
 
+void
+free_ls(struct lsstruct *lssp)
+{
+    while(lssp) {
+        struct lsstruct *lsspn = lssp->next;
+        xfree(lssp->lserver);
+        xfree(lssp->domain);
+        xfree(lssp);
+        lssp = lsspn;
+    }
+}
+
 int
 create_ls(struct main_args *margs)
 {
@@ -73,18 +85,19 @@ create_ls(struct main_args *margs)
         if (*p == '@') {       /* end of group name - start of domain name */
             if (p == np) {     /* empty group name not allowed */
                 debug((char *) "%s| %s: DEBUG: No ldap servers defined for domain %s\n", LogTime(), PROGRAM, p);
+                free_ls(lssp);
                 return (1);
             }
             *p = '\0';
             ++p;
             lssp = init_ls();
             lssp->lserver = xstrdup(np);
-            if (lsspn)         /* Have already an existing structure */
-                lssp->next = lsspn;
+            lssp->next = lsspn;
             dp = p;            /* after @ starts new domain name */
         } else if (*p == ':') {        /* end of group name or end of domain name */
             if (p == np) {     /* empty group name not allowed */
                 debug((char *) "%s| %s: DEBUG: No ldap servers defined for domain %s\n", LogTime(), PROGRAM, p);
+                free_ls(lssp);
                 return (1);
             }
             *p = '\0';
@@ -95,8 +108,7 @@ create_ls(struct main_args *margs)
             } else {           /* end of group name and no domain name */
                 lssp = init_ls();
                 lssp->lserver = xstrdup(np);
-                if (lsspn)     /* Have already an existing structure */
-                    lssp->next = lsspn;
+                lssp->next = lsspn;
             }
             lsspn = lssp;
             np = p;            /* after : starts new group name */
@@ -106,6 +118,7 @@ create_ls(struct main_args *margs)
     }
     if (p == np) {             /* empty group name not allowed */
         debug((char *) "%s| %s: DEBUG: No ldap servers defined for domain %s\n", LogTime(), PROGRAM, p);
+        free_ls(lssp);
         return (1);
     }
     if (dp) {                  /* end of domain name */
index a7213855788e973e94c1063bc6311d0c79bbf0bd..4016dfa768041c242411f77a47fa459bcaf9ae5a 100644 (file)
@@ -41,6 +41,18 @@ init_nd(void) {
     return ndsp;
 }
 
+void
+free_nd(struct ndstruct *ndsp)
+{
+    while (ndsp) {
+        struct ndstruct *ndspn = ndsp->next;
+        xfree(ndsp->netbios);
+        xfree(ndsp->domain);
+        xfree(ndsp);
+        ndsp = ndspn;
+    }
+}
+
 int
 create_nd(struct main_args *margs)
 {
@@ -74,18 +86,19 @@ create_nd(struct main_args *margs)
         if (*p == '@') {       /* end of group name - start of domain name */
             if (p == np) {     /* empty group name not allowed */
                 debug((char *) "%s| %s: DEBUG: No netbios name defined for domain %s\n", LogTime(), PROGRAM, p);
+                free_nd(ndsp);
                 return (1);
             }
             *p = '\0';
             ++p;
             ndsp = init_nd();
             ndsp->netbios = xstrdup(np);
-            if (ndspn)         /* Have already an existing structure */
-                ndsp->next = ndspn;
+            ndsp->next = ndspn;
             dp = p;            /* after @ starts new domain name */
         } else if (*p == ':') {        /* end of group name or end of domain name */
             if (p == np) {     /* empty group name not allowed */
                 debug((char *) "%s| %s: DEBUG: No netbios name defined for domain %s\n", LogTime(), PROGRAM, p);
+                free_nd(ndsp);
                 return (1);
             }
             *p = '\0';
@@ -96,13 +109,13 @@ create_nd(struct main_args *margs)
             } else {           /* end of group name and no domain name */
                 ndsp = init_nd();
                 ndsp->netbios = xstrdup(np);
-                if (ndspn)     /* Have already an existing structure */
-                    ndsp->next = ndspn;
+                ndsp->next = ndspn;
             }
             ndspn = ndsp;
             np = p;            /* after : starts new group name */
             if (!ndsp->domain || !strcmp(ndsp->domain, "")) {
                 debug((char *) "%s| %s: DEBUG: No domain defined for netbios name %s\n", LogTime(), PROGRAM, ndsp->netbios);
+                free_nd(ndsp);
                 return (1);
             }
             debug((char *) "%s| %s: DEBUG: Netbios name %s  Domain %s\n", LogTime(), PROGRAM, ndsp->netbios, ndsp->domain);
@@ -111,6 +124,7 @@ create_nd(struct main_args *margs)
     }
     if (p == np) {             /* empty group name not allowed */
         debug((char *) "%s| %s: DEBUG: No netbios name defined for domain %s\n", LogTime(), PROGRAM, p);
+        free_nd(ndsp);
         return (1);
     }
     if (dp) {                  /* end of domain name */
@@ -118,11 +132,11 @@ create_nd(struct main_args *margs)
     } else {                   /* end of group name and no domain name */
         ndsp = init_nd();
         ndsp->netbios = xstrdup(np);
-        if (ndspn)             /* Have already an existing structure */
-            ndsp->next = ndspn;
+        ndsp->next = ndspn;
     }
     if (!ndsp->domain || !strcmp(ndsp->domain, "")) {
         debug((char *) "%s| %s: DEBUG: No domain defined for netbios name %s\n", LogTime(), PROGRAM, ndsp->netbios);
+        free_nd(ndsp);
         return (1);
     }
     debug((char *) "%s| %s: DEBUG: Netbios name %s  Domain %s\n", LogTime(), PROGRAM, ndsp->netbios, ndsp->domain);