Disallow all special operators once groups are used.

+ and - should also be forbidden. Any operation other than appending will mix
up the in_group bits and give unexpected behavior.

Change-Id: Ieaebb9ee6393aa36243d0765e45cae667f977ef5
Reviewed-on: https://boringssl-review.googlesource.com/1803
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index eb28656..fbed548 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -761,20 +761,8 @@
 			{ rule = CIPHER_DEL; l++; }
 		else if (ch == '+')
 			{ rule = CIPHER_ORD; l++; }
-		else if (ch == '!' && has_group)
-			{
-			OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
-			retval = found = in_group = 0;
-			break;
-			}
 		else if (ch == '!')
 			{ rule = CIPHER_KILL; l++; }
-		else if (ch == '@' && has_group)
-			{
-			OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
-			retval = found = in_group = 0;
-			break;
-			}
 		else if (ch == '@')
 			{ rule = CIPHER_SPECIAL; l++; }
 		else if (ch == '[')
@@ -793,6 +781,16 @@
 		else
 			{ rule = CIPHER_ADD; }
 
+		/* If preference groups are enabled, the only legal
+		 * operator is +. Otherwise the in_group bits will get
+		 * mixed up. */
+		if (has_group && rule != CIPHER_ADD)
+			{
+			OPENSSL_PUT_ERROR(SSL, ssl_cipher_process_rulestr, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
+			retval = found = in_group = 0;
+			break;
+			}
+
 		if (ITEM_SEP(ch))
 			{
 			l++;