svn rev #22326: trunk/src/lib/krb5/os/

ghudson@MIT.EDU ghudson at MIT.EDU
Mon May 11 12:57:46 EDT 2009


http://src.mit.edu/fisheye/changelog/krb5/?cs=22326
Commit By: ghudson
Log Message:
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.



Changed Files:
U   trunk/src/lib/krb5/os/Makefile.in
U   trunk/src/lib/krb5/os/an_to_ln.c
Modified: trunk/src/lib/krb5/os/Makefile.in
===================================================================
--- trunk/src/lib/krb5/os/Makefile.in	2009-05-07 20:35:28 UTC (rev 22325)
+++ trunk/src/lib/krb5/os/Makefile.in	2009-05-11 16:57:45 UTC (rev 22326)
@@ -221,6 +221,8 @@
 #	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 @@
 	KRB5_CONFIG=./t_an.conf ; export KRB5_CONFIG ; \
 	$(KRB5_RUN_ENV) $(VALGRIND) ./t_an_to_ln rul/helpme/e at r ru/123/le at r
 	KRB5_CONFIG=./t_an.conf ; export KRB5_CONFIG ; \
-	$(KRB5_RUN_ENV) $(VALGRIND) ./t_an_to_ln fred/r at r barney/r at r
+	$(KRB5_RUN_ENV) $(VALGRIND) ./t_an_to_ln fred/r at r barney/r at r x/r/r/r at r
 	$(RM) ./t_an.*
 
 clean:: 

Modified: trunk/src/lib/krb5/os/an_to_ln.c
===================================================================
--- trunk/src/lib/krb5/os/an_to_ln.c	2009-05-07 20:35:28 UTC (rev 22325)
+++ trunk/src/lib/krb5/os/an_to_ln.c	2009-05-11 16:57:45 UTC (rev 22326)
@@ -481,142 +481,119 @@
 }
 
 /*
- * 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, &current, 10);
+    if (errno != 0 || num_comps < 0 || *current != ':')
+	return KRB5_CONFIG_BADFORMAT;
+    if (num_comps != aname->length)
+	return KRB5_LNAME_NOTRANS;
+    current++;
 
-			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);
+    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, &current, 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);
     }
-    if (!kret) {
-	/*
-	 * Second part
-	 */
-	if (*current == '(')
-	    kret = aname_do_match(selstring, &current);
 
-	/*
-	 * Third part.
-	 */
-	if (!kret) {
-	    outstring = (char *) NULL;
-	    kret = aname_replacer(selstring, &current, &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);
+    /* Check that we hit a ']' and not the end of the string. */
+    if (*current != ']') {
+	krb5int_free_buf(&selstring);
+	return KRB5_CONFIG_BADFORMAT;
     }
 
-    return(kret);
+    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, &current, &selstring);
+    if (kret)
+	return kret;
+
+    /* Check the selection string against the regexp, if present. */
+    if (*current == '(') {
+	kret = aname_do_match(selstring, &current);
+	if (kret)
+	    goto cleanup;
+    }
+
+    /* Perform the substitution. */
+    outstring = NULL;
+    kret = aname_replacer(selstring, &current, &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 */
 
 /*




More information about the cvs-krb5 mailing list