fix buffer overflow in an_to_ln.c
authorTom Yu <tlyu@mit.edu>
Tue, 1 Jun 2004 20:16:38 +0000 (20:16 +0000)
committerTom Yu <tlyu@mit.edu>
Tue, 1 Jun 2004 20:16:38 +0000 (20:16 +0000)
* an_to_ln.c (rule_an_to_ln): Fix buffer overflow when parsing
principal names into components.
(do_replacement): likewise
(aname_replacer): Support error return from do_replacement

ticket: new
version_reported: 1.3.3
target_version: 1.3.4
tags: pullup
component: krb5-libs

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@16381 dc483132-0cff-0310-8789-dd5450dbe970

src/lib/krb5/os/ChangeLog
src/lib/krb5/os/an_to_ln.c

index 59c24dc0d5a7471822429916c96d024dfd549f0d..790bc2f2b494bd0e84a7aaeabd5f7ef04ebbe3c3 100644 (file)
@@ -1,3 +1,10 @@
+2004-06-01  Sam Hartman  <hartmans@mit.edu>
+
+       * an_to_ln.c (rule_an_to_ln): Fix buffer overflow when parsing
+       principal names into components. 
+       (do_replacement): likewise
+       (aname_replacer): Support error return from do_replacement
+
 2004-05-07  Sam Hartman  <hartmans@mit.edu>
 
        * an_to_ln.c: Patch from Matt Crawford  to allow matching on
index 41a5bde3130489364f79dabee551caaa1fd63f03..c134cafcfc848dfb5367ac7c66ad0161e065dc1b 100644 (file)
@@ -270,9 +270,14 @@ aname_do_match(char *string, char **contextp)
  * If no regcomp() then just return the input string verbatim in the output
  * string.
  */
-static void
+#define use_bytes(x) \
+    out_used += (x); \
+    if (out_used > MAX_FORMAT_BUFFER) goto mem_err
+
+static int
 do_replacement(char *regexp, char *repl, int doall, char *in, char *out)
 {
+    size_t out_used = 0;
 #if    HAVE_REGCOMP
     regex_t    match_exp;
     regmatch_t match_match;
@@ -287,17 +292,22 @@ do_replacement(char *regexp, char *repl, int doall, char *in, char *out)
        do {
            if (!regexec(&match_exp, cp, 1, &match_match, 0)) {
                if (match_match.rm_so) {
+                   use_bytes(match_match.rm_so);
                    strncpy(op, cp, match_match.rm_so);
                    op += match_match.rm_so;
                }
+               use_bytes(strlen(repl));
                strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out));
                op += strlen(op);
                cp += match_match.rm_eo;
-               if (!doall)
+               if (!doall) {
+                   use_bytes(strlen(cp));
                    strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
+               }
                matched = 1;
            }
            else {
+               use_bytes(strlen(cp));
                strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
                matched = 0;
            }
@@ -322,17 +332,21 @@ do_replacement(char *regexp, char *repl, int doall, char *in, char *out)
            sdispl = (size_t) (loc1 - cp);
            edispl = (size_t) (loc2 - cp);
            if (sdispl) {
+               use_bytes(sdispl);
                strncpy(op, cp, sdispl);
                op += sdispl;
            }
+           use_bytes(strlen(repl));
            strncpy(op, repl, MAX_FORMAT_BUFFER - 1 - (op - out));
            op += strlen(repl);
            cp += edispl;
            if (!doall)
+               use_bytes(strlen(cp));
                strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
            matched = 1;
        }
        else {
+           use_bytes(strlen(cp));
            strncpy(op, cp, MAX_FORMAT_BUFFER - 1 - (op - out));
            matched = 0;
        }
@@ -340,7 +354,15 @@ do_replacement(char *regexp, char *repl, int doall, char *in, char *out)
 #else  /* HAVE_REGEXP_H */
     memcpy(out, in, MAX_FORMAT_BUFFER);
 #endif /* HAVE_REGCOMP */
+    return 1;
+ mem_err:
+#ifdef HAVE_REGCMP
+       regfree(&match_exp);
+#endif
+       return 0;
+       
 }
+#undef use_bytes
 
 /*
  * aname_replacer()    - Perform the specified substitutions on the input
@@ -412,7 +434,12 @@ aname_replacer(char *string, char **contextp, char **result)
 
                    /* Do the replacemenbt */
                    memset(out, '\0', MAX_FORMAT_BUFFER);
-                   do_replacement(rule, repl, doglobal, in, out);
+                   if (!do_replacement(rule, repl, doglobal, in, out)) {
+                       free(rule);
+                   free(repl);
+                       kret = KRB5_LNAME_NOTRANS;
+                       break;
+                   }
                    free(rule);
                    free(repl);
 
@@ -459,6 +486,7 @@ rule_an_to_ln(krb5_context context, char *rule, krb5_const_principal aname, cons
     char               *fprincname;
     char               *selstring = 0;
     int                        num_comps, compind;
+    size_t selstring_used;
     char               *cout;
     krb5_const krb5_data *datap;
     char               *outstring;
@@ -479,6 +507,7 @@ rule_an_to_ln(krb5_context context, char *rule, krb5_const_principal aname, cons
                     */
                    current = strchr(current, ':');
                    selstring = (char *) malloc(MAX_FORMAT_BUFFER);
+                   selstring_used = 0;
                    if (current && selstring) {
                        current++;
                        cout = selstring;
@@ -499,6 +528,14 @@ rule_an_to_ln(krb5_context context, char *rule, krb5_const_principal aname, cons
                                                            compind-1)
                                     : krb5_princ_realm(context, aname))
                                    ) {
+                                   if ((datap->length < MAX_FORMAT_BUFFER)
+                                       &&  (selstring_used+datap->length
+                                            < MAX_FORMAT_BUFFER)) {
+                                       selstring_used += datap->length;
+                                   } else {
+                                       kret = ENOMEM;
+                                       goto errout;
+                                   }
                                    strncpy(cout,
                                            datap->data,
                                            (unsigned) datap->length);
@@ -529,7 +566,7 @@ rule_an_to_ln(krb5_context context, char *rule, krb5_const_principal aname, cons
                        else
                            kret = KRB5_CONFIG_BADFORMAT;
 
-                       if (kret)
+                       errout: if (kret)
                            free(selstring);
                    }
                }