From 292415b758d58df15aff93c644a45e070afcc2fc Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Mon, 11 May 2009 16:57:45 +0000 Subject: [PATCH] Refactor rule_an_to_ln, creating a new helper function to handle the selection string specifier. Eliminate two (safe) uses of sscanf in the process. Add a test case including literal text in the selection string specifier. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@22326 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/os/Makefile.in | 4 +- src/lib/krb5/os/an_to_ln.c | 225 ++++++++++++++++-------------------- 2 files changed, 104 insertions(+), 125 deletions(-) diff --git a/src/lib/krb5/os/Makefile.in b/src/lib/krb5/os/Makefile.in index 4998e0fae..824f91365 100644 --- a/src/lib/krb5/os/Makefile.in +++ b/src/lib/krb5/os/Makefile.in @@ -221,6 +221,8 @@ check-unix:: # fi echo 'auth_to_local = RULE:[3:$$1$$3$$2](rule.*)s/rule//g' \ >> ./t_an.conf + echo 'auth_to_local = RULE:[4:wi$$1ma]s/x/l/g' \ + >> ./t_an.conf echo 'auth_to_local = DEFAULT' >> ./t_an.conf echo '}' >> ./t_an.conf # if test -r ../../../admin/aname/kdb5_anadd ; then \ @@ -230,7 +232,7 @@ check-unix:: KRB5_CONFIG=./t_an.conf ; export KRB5_CONFIG ; \ $(KRB5_RUN_ENV) $(VALGRIND) ./t_an_to_ln rul/helpme/e@r ru/123/le@r KRB5_CONFIG=./t_an.conf ; export KRB5_CONFIG ; \ - $(KRB5_RUN_ENV) $(VALGRIND) ./t_an_to_ln fred/r@r barney/r@r + $(KRB5_RUN_ENV) $(VALGRIND) ./t_an_to_ln fred/r@r barney/r@r x/r/r/r@r $(RM) ./t_an.* clean:: diff --git a/src/lib/krb5/os/an_to_ln.c b/src/lib/krb5/os/an_to_ln.c index ed9bc96ca..731b76b84 100644 --- a/src/lib/krb5/os/an_to_ln.c +++ b/src/lib/krb5/os/an_to_ln.c @@ -481,141 +481,118 @@ cleanup: } /* - * rule_an_to_ln() - Handle aname to lname translations for RULE rules. + * Compute selection string for RULE rules. * - * The initial part of this routine handles the formulation of the strings from - * the principal name. + * Advance *contextp to the string position after the selectring + * string part if present, and set *result to the selection string. */ static krb5_error_code -rule_an_to_ln(krb5_context context, char *rule, krb5_const_principal aname, const unsigned int lnsize, char *lname) +aname_get_selstring(krb5_context context, krb5_const_principal aname, + char **contextp, char **result) { - krb5_error_code kret; - char *current; - char *fprincname; - char *selstring = 0; - int num_comps, compind, pos; - size_t selstring_used; - char *cout; - krb5_const krb5_data *datap; - char *outstring; + krb5_error_code kret; + char *fprincname, *current, *str; + long num_comps, compind; + const krb5_data *datap; + struct k5buf selstring; + size_t nlit; - /* - * First flatten the name. - */ - current = rule; - if (!(kret = krb5_unparse_name(context, aname, &fprincname))) { - /* - * First part. - */ - if (*current == '[') { - current++; - if (sscanf(current,"%d:%n", &num_comps, &pos) == 1) { - if (num_comps == aname->length) { - /* - * We have a match based on the number of components. - */ - current += pos; - selstring = (char *) malloc(MAX_FORMAT_BUFFER); - selstring_used = 0; - if (selstring) { - cout = selstring; - /* - * Plow through the string. - */ - while ((*current != ']') && - (*current != '\0')) { - /* - * Expand to a component. - */ - if (*current == '$') { - if ((sscanf(current+1, "%d", &compind) == 1) && - (compind <= num_comps) && - (datap = - (compind > 0) - ? krb5_princ_component(context, aname, - 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); - cout += datap->length; - *cout = '\0'; - current++; - /* Point past number */ - while (isdigit((int) (*current))) - current++; - } - else - kret = KRB5_CONFIG_BADFORMAT; - } - else { - /* Copy in verbatim. */ - *cout = *current; - cout++; - *cout = '\0'; - current++; - } - } + *result = NULL; + if (**contextp != '[') { + /* No selstring part; use the full flattened principal name. */ + kret = krb5_unparse_name(context, aname, &fprincname); + if (kret) + return kret; + str = aname_full_to_mapping_name(fprincname); + free(fprincname); + if (!str) + return ENOMEM; + *result = str; + return 0; + } - /* - * Advance past separator if appropriate. - */ - if (*current == ']') - current++; - else - kret = KRB5_CONFIG_BADFORMAT; + /* Advance past the '[' and read the number of components. */ + current = *contextp + 1; + errno = 0; + num_comps = strtol(current, ¤t, 10); + if (errno != 0 || num_comps < 0 || *current != ':') + return KRB5_CONFIG_BADFORMAT; + if (num_comps != aname->length) + return KRB5_LNAME_NOTRANS; + current++; + + krb5int_buf_init_dynamic(&selstring); + while (1) { + /* Copy in literal characters up to the next $ or ]. */ + nlit = strcspn(current, "$]"); + krb5int_buf_add_len(&selstring, current, nlit); + current += nlit; + if (*current != '$') + break; + + /* Expand $ substitution to a principal component. */ + errno = 0; + compind = strtol(current + 1, ¤t, 10); + if (errno || compind > num_comps) + break; + datap = (compind > 0) + ? krb5_princ_component(context, aname, compind - 1) + : krb5_princ_realm(context, aname); + if (!datap) + break; + krb5int_buf_add_len(&selstring, datap->data, datap->length); + } - errout: if (kret) - free(selstring); - } - else - kret = ENOMEM; - } - else - kret = KRB5_LNAME_NOTRANS; - } - else - kret = KRB5_CONFIG_BADFORMAT; - } - else { - if (!(selstring = aname_full_to_mapping_name(fprincname))) - kret = ENOMEM; - } - free(fprincname); + /* Check that we hit a ']' and not the end of the string. */ + if (*current != ']') { + krb5int_free_buf(&selstring); + return KRB5_CONFIG_BADFORMAT; } - if (!kret) { - /* - * Second part - */ - if (*current == '(') - kret = aname_do_match(selstring, ¤t); - /* - * Third part. - */ - if (!kret) { - outstring = (char *) NULL; - kret = aname_replacer(selstring, ¤t, &outstring); - if (outstring) { - /* Copy out the value if there's enough room */ - if (strlcpy(lname, outstring, lnsize) >= lnsize) - kret = KRB5_CONFIG_NOTENUFSPACE; - free(outstring); - } - } - free(selstring); + str = krb5int_buf_data(&selstring); + if (str == NULL) + return ENOMEM; + + *contextp = current + 1; + *result = str; + return 0; +} + +/* Handle aname to lname translations for RULE rules. */ +static krb5_error_code +rule_an_to_ln(krb5_context context, char *rule, krb5_const_principal aname, + const unsigned int lnsize, char *lname) +{ + krb5_error_code kret; + char *current, *selstring = 0, *outstring = 0; + + /* Compute the selection string. */ + current = rule; + kret = aname_get_selstring(context, aname, ¤t, &selstring); + if (kret) + return kret; + + /* Check the selection string against the regexp, if present. */ + if (*current == '(') { + kret = aname_do_match(selstring, ¤t); + if (kret) + goto cleanup; } - return(kret); + /* Perform the substitution. */ + outstring = NULL; + kret = aname_replacer(selstring, ¤t, &outstring); + if (kret) + goto cleanup; + + /* Copy out the value if there's enough room. */ + if (strlcpy(lname, outstring, lnsize) >= lnsize) + kret = KRB5_CONFIG_NOTENUFSPACE; + +cleanup: + free(selstring); + free(outstring); + return kret; } #endif /* AN_TO_LN_RULES */ -- 2.26.2