1
0
mirror of https://github.com/hashcat/hashcat.git synced 2024-11-28 19:08:19 +00:00

Add support to character class rules

This commit is contained in:
Gabriele Gristina 2024-11-02 22:02:18 +01:00
parent 157782da66
commit 53f57fb7ae
10 changed files with 1247 additions and 315 deletions

View File

@ -577,6 +577,90 @@ DECLSPEC int mangle_replace (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1,
return (len);
}
DECLSPEC int mangle_replace_class_l (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len)
{
for (int pos = 0; pos < len; pos++)
{
if (!is_l (buf[pos])) continue;
buf[pos] = p1;
}
return (len);
}
DECLSPEC int mangle_replace_class_u (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len)
{
for (int pos = 0; pos < len; pos++)
{
if (!is_u (buf[pos])) continue;
buf[pos] = p1;
}
return (len);
}
DECLSPEC int mangle_replace_class_d (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len)
{
for (int pos = 0; pos < len; pos++)
{
if (!is_d (buf[pos])) continue;
buf[pos] = p1;
}
return (len);
}
DECLSPEC int mangle_replace_class_lh (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len)
{
for (int pos = 0; pos < len; pos++)
{
if (!is_lh (buf[pos])) continue;
buf[pos] = p1;
}
return (len);
}
DECLSPEC int mangle_replace_class_uh (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len)
{
for (int pos = 0; pos < len; pos++)
{
if (!is_uh (buf[pos])) continue;
buf[pos] = p1;
}
return (len);
}
DECLSPEC int mangle_replace_class_s (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len)
{
for (int pos = 0; pos < len; pos++)
{
if (!is_s (buf[pos])) continue;
buf[pos] = p1;
}
return (len);
}
DECLSPEC int mangle_replace_class (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len)
{
if (p0 == 'l') return mangle_replace_class_l (p0, p1, buf, len);
else if (p0 == 'u') return mangle_replace_class_u (p0, p1, buf, len);
else if (p0 == 'd') return mangle_replace_class_d (p0, p1, buf, len);
else if (p0 == 'h') return mangle_replace_class_lh (p0, p1, buf, len);
else if (p0 == 'H') return mangle_replace_class_uh (p0, p1, buf, len);
else if (p0 == 's') return mangle_replace_class_s (p0, p1, buf, len);
return len;
}
DECLSPEC int mangle_purgechar (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len)
{
int out_len = 0;
@ -965,6 +1049,7 @@ DECLSPEC int apply_rule (const u32 name, MAYBE_UNUSED const u8 p0, MAYBE_UNUSED
case RULE_OP_MANGLE_OVERSTRIKE: out_len = mangle_overstrike (p0, p1, (PRIVATE_AS u8 *) buf, out_len); break;
case RULE_OP_MANGLE_TRUNCATE_AT: out_len = mangle_truncate_at (p0, p1, (PRIVATE_AS u8 *) buf, out_len); break;
case RULE_OP_MANGLE_REPLACE: out_len = mangle_replace (p0, p1, (PRIVATE_AS u8 *) buf, out_len); break;
case RULE_OP_MANGLE_REPLACE_CLASS: out_len = mangle_replace_class (p0, p1, (PRIVATE_AS u8 *) buf, out_len); break;
case RULE_OP_MANGLE_PURGECHAR: out_len = mangle_purgechar (p0, p1, (PRIVATE_AS u8 *) buf, out_len); break;
case RULE_OP_MANGLE_PURGECHAR_CLASS: out_len = mangle_purgechar_class (p0, p1, (PRIVATE_AS u8 *) buf, out_len); break;
case RULE_OP_MANGLE_DUPECHAR_FIRST: out_len = mangle_dupechar_first (p0, p1, (PRIVATE_AS u8 *) buf, out_len); break;

View File

@ -40,7 +40,6 @@
#define RULE_OP_MANGLE_TRUNCATE_AT '\''
#define RULE_OP_MANGLE_REPLACE 's'
#define RULE_OP_MANGLE_PURGECHAR '@'
#define RULE_OP_MANGLE_PURGECHAR_CLASS 0x01
#define RULE_OP_MANGLE_TOGGLECASE_REC 'a'
#define RULE_OP_MANGLE_DUPECHAR_FIRST 'z'
#define RULE_OP_MANGLE_DUPECHAR_LAST 'Z'
@ -70,6 +69,17 @@
#define RULE_OP_MANGLE_DUPEBLOCK_LAST 'Y'
#define RULE_OP_MANGLE_TITLE 'E'
/* using character classes */
#define RULE_OP_MANGLE_REPLACE_CLASS 0x01
#define RULE_OP_MANGLE_PURGECHAR_CLASS 0x02
#define RULE_OP_REJECT_CONTAIN_CLASS 0x03
#define RULE_OP_REJECT_NOT_CONTAIN_CLASS 0x04
#define RULE_OP_REJECT_EQUAL_FIRST_CLASS 0x05
#define RULE_OP_REJECT_EQUAL_LAST_CLASS 0x06
#define RULE_OP_REJECT_EQUAL_AT_CLASS 0x07
#define RULE_OP_REJECT_CONTAINS_CLASS 0x08
#define RP_PASSWORD_SIZE 256
DECLSPEC u32 generate_cmask (const u32 value);
@ -103,6 +113,7 @@ DECLSPEC int mangle_insert (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1,
DECLSPEC int mangle_overstrike (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len);
DECLSPEC int mangle_truncate_at (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len);
DECLSPEC int mangle_replace (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len);
DECLSPEC int mangle_replace_class (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len);
DECLSPEC int mangle_purgechar (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len);
DECLSPEC int mangle_purgechar_class (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len);
DECLSPEC int mangle_dupechar_first (MAYBE_UNUSED const u8 p0, MAYBE_UNUSED const u8 p1, PRIVATE_AS u8 *buf, const int len);

View File

@ -1825,6 +1825,258 @@ DECLSPEC HC_INLINE_RP u32 rule_op_mangle_replace (MAYBE_UNUSED const u32 p0, MAY
return in_len;
}
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_replace_class_l (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len)
{
u32 buf_in[8];
buf_in[0] = buf0[0];
buf_in[1] = buf0[1];
buf_in[2] = buf0[2];
buf_in[3] = buf0[3];
buf_in[4] = buf1[0];
buf_in[5] = buf1[1];
buf_in[6] = buf1[2];
buf_in[7] = buf1[3];
PRIVATE_AS u8 *in = (PRIVATE_AS u8 *) buf_in;
u32 rn = 0;
for (u32 pos = 0; pos < in_len; pos++)
{
if (!is_l (in[pos])) continue;
in[pos] = (u8)p1;
rn++;
}
if (rn == 0) return in_len;
buf0[0] = buf_in[0];
buf0[1] = buf_in[1];
buf0[2] = buf_in[2];
buf0[3] = buf_in[3];
buf1[0] = buf_in[4];
buf1[1] = buf_in[5];
buf1[2] = buf_in[6];
buf1[3] = buf_in[7];
return in_len;
}
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_replace_class_u (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len)
{
u32 buf_in[8];
buf_in[0] = buf0[0];
buf_in[1] = buf0[1];
buf_in[2] = buf0[2];
buf_in[3] = buf0[3];
buf_in[4] = buf1[0];
buf_in[5] = buf1[1];
buf_in[6] = buf1[2];
buf_in[7] = buf1[3];
PRIVATE_AS u8 *in = (PRIVATE_AS u8 *) buf_in;
u32 rn = 0;
for (u32 pos = 0; pos < in_len; pos++)
{
if (!is_u (in[pos])) continue;
in[pos] = (u8)p1;
rn++;
}
if (rn == 0) return in_len;
buf0[0] = buf_in[0];
buf0[1] = buf_in[1];
buf0[2] = buf_in[2];
buf0[3] = buf_in[3];
buf1[0] = buf_in[4];
buf1[1] = buf_in[5];
buf1[2] = buf_in[6];
buf1[3] = buf_in[7];
return in_len;
}
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_replace_class_d (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len)
{
u32 buf_in[8];
buf_in[0] = buf0[0];
buf_in[1] = buf0[1];
buf_in[2] = buf0[2];
buf_in[3] = buf0[3];
buf_in[4] = buf1[0];
buf_in[5] = buf1[1];
buf_in[6] = buf1[2];
buf_in[7] = buf1[3];
PRIVATE_AS u8 *in = (PRIVATE_AS u8 *) buf_in;
u32 rn = 0;
for (u32 pos = 0; pos < in_len; pos++)
{
if (!is_d (in[pos])) continue;
in[pos] = (u8)p1;
rn++;
}
if (rn == 0) return in_len;
buf0[0] = buf_in[0];
buf0[1] = buf_in[1];
buf0[2] = buf_in[2];
buf0[3] = buf_in[3];
buf1[0] = buf_in[4];
buf1[1] = buf_in[5];
buf1[2] = buf_in[6];
buf1[3] = buf_in[7];
return in_len;
}
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_replace_class_lh (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len)
{
u32 buf_in[8];
buf_in[0] = buf0[0];
buf_in[1] = buf0[1];
buf_in[2] = buf0[2];
buf_in[3] = buf0[3];
buf_in[4] = buf1[0];
buf_in[5] = buf1[1];
buf_in[6] = buf1[2];
buf_in[7] = buf1[3];
PRIVATE_AS u8 *in = (PRIVATE_AS u8 *) buf_in;
u32 rn = 0;
for (u32 pos = 0; pos < in_len; pos++)
{
if (!is_lh (in[pos])) continue;
in[pos] = (u8)p1;
rn++;
}
if (rn == 0) return in_len;
buf0[0] = buf_in[0];
buf0[1] = buf_in[1];
buf0[2] = buf_in[2];
buf0[3] = buf_in[3];
buf1[0] = buf_in[4];
buf1[1] = buf_in[5];
buf1[2] = buf_in[6];
buf1[3] = buf_in[7];
return in_len;
}
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_replace_class_uh (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len)
{
u32 buf_in[8];
buf_in[0] = buf0[0];
buf_in[1] = buf0[1];
buf_in[2] = buf0[2];
buf_in[3] = buf0[3];
buf_in[4] = buf1[0];
buf_in[5] = buf1[1];
buf_in[6] = buf1[2];
buf_in[7] = buf1[3];
PRIVATE_AS u8 *in = (PRIVATE_AS u8 *) buf_in;
u32 rn = 0;
for (u32 pos = 0; pos < in_len; pos++)
{
if (!is_uh (in[pos])) continue;
in[pos] = (u8)p1;
rn++;
}
if (rn == 0) return in_len;
buf0[0] = buf_in[0];
buf0[1] = buf_in[1];
buf0[2] = buf_in[2];
buf0[3] = buf_in[3];
buf1[0] = buf_in[4];
buf1[1] = buf_in[5];
buf1[2] = buf_in[6];
buf1[3] = buf_in[7];
return in_len;
}
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_replace_class_s (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len)
{
u32 buf_in[8];
buf_in[0] = buf0[0];
buf_in[1] = buf0[1];
buf_in[2] = buf0[2];
buf_in[3] = buf0[3];
buf_in[4] = buf1[0];
buf_in[5] = buf1[1];
buf_in[6] = buf1[2];
buf_in[7] = buf1[3];
PRIVATE_AS u8 *in = (PRIVATE_AS u8 *) buf_in;
u32 rn = 0;
for (u32 pos = 0; pos < in_len; pos++)
{
if (!is_s (in[pos])) continue;
in[pos] = (u8)p1;
rn++;
}
if (rn == 0) return in_len;
buf0[0] = buf_in[0];
buf0[1] = buf_in[1];
buf0[2] = buf_in[2];
buf0[3] = buf_in[3];
buf1[0] = buf_in[4];
buf1[1] = buf_in[5];
buf1[2] = buf_in[6];
buf1[3] = buf_in[7];
return in_len;
}
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_replace_class (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len)
{
if ((u8)p0 == 'l') return rule_op_mangle_replace_class_l (p0, p1, buf0, buf1, in_len);
else if ((u8)p0 == 'u') return rule_op_mangle_replace_class_u (p0, p1, buf0, buf1, in_len);
else if ((u8)p0 == 'd') return rule_op_mangle_replace_class_d (p0, p1, buf0, buf1, in_len);
else if ((u8)p0 == 'h') return rule_op_mangle_replace_class_lh (p0, p1, buf0, buf1, in_len);
else if ((u8)p0 == 'H') return rule_op_mangle_replace_class_uh (p0, p1, buf0, buf1, in_len);
else if ((u8)p0 == 's') return rule_op_mangle_replace_class_s (p0, p1, buf0, buf1, in_len);
return in_len;
}
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_purgechar (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len)
{
const u32 r0 = search_on_register (buf0[0], p0);
@ -2692,6 +2944,7 @@ DECLSPEC u32 apply_rule_optimized (const u32 name, const u32 p0, const u32 p1, P
case RULE_OP_MANGLE_OVERSTRIKE: out_len = rule_op_mangle_overstrike (p0, p1, buf0, buf1, out_len); break;
case RULE_OP_MANGLE_TRUNCATE_AT: out_len = rule_op_mangle_truncate_at (p0, p1, buf0, buf1, out_len); break;
case RULE_OP_MANGLE_REPLACE: out_len = rule_op_mangle_replace (p0, p1, buf0, buf1, out_len); break;
case RULE_OP_MANGLE_REPLACE_CLASS: out_len = rule_op_mangle_replace_class (p0, p1, buf0, buf1, out_len); break;
case RULE_OP_MANGLE_PURGECHAR: out_len = rule_op_mangle_purgechar (p0, p1, buf0, buf1, out_len); break;
case RULE_OP_MANGLE_PURGECHAR_CLASS: out_len = rule_op_mangle_purgechar_class (p0, p1, buf0, buf1, out_len); break;
//case RULE_OP_MANGLE_TOGGLECASE_REC: out_len = rule_op_mangle_togglecase_rec (p0, p1, buf0, buf1, out_len); break;

View File

@ -46,7 +46,6 @@
#define RULE_OP_MANGLE_TRUNCATE_AT '\''
#define RULE_OP_MANGLE_REPLACE 's'
#define RULE_OP_MANGLE_PURGECHAR '@'
#define RULE_OP_MANGLE_PURGECHAR_CLASS 0x01
#define RULE_OP_MANGLE_TOGGLECASE_REC 'a'
#define RULE_OP_MANGLE_DUPECHAR_FIRST 'z'
#define RULE_OP_MANGLE_DUPECHAR_LAST 'Z'
@ -76,6 +75,16 @@
#define RULE_OP_MANGLE_DUPEBLOCK_LAST 'Y'
#define RULE_OP_MANGLE_TITLE 'E'
/* using character classes */
#define RULE_OP_MANGLE_REPLACE_CLASS 0x01
#define RULE_OP_MANGLE_PURGECHAR_CLASS 0x02
#define RULE_OP_REJECT_CONTAIN_CLASS 0x03
#define RULE_OP_REJECT_NOT_CONTAIN_CLASS 0x04
#define RULE_OP_REJECT_EQUAL_FIRST_CLASS 0x05
#define RULE_OP_REJECT_EQUAL_LAST_CLASS 0x06
#define RULE_OP_REJECT_EQUAL_AT_CLASS 0x07
#define RULE_OP_REJECT_CONTAINS_CLASS 0x08
DECLSPEC u32 generate_cmask_optimized (const u32 value);
DECLSPEC void truncate_right_optimized (PRIVATE_AS u32 *buf0, PRIVATE_AS u32 *buf1, const u32 offset);
DECLSPEC void truncate_left_optimized (PRIVATE_AS u32 *buf0, PRIVATE_AS u32 *buf1, const u32 offset);
@ -113,6 +122,7 @@ DECLSPEC HC_INLINE_RP u32 rule_op_mangle_truncate_at (MAYBE_UNUSED const u32 p0,
DECLSPEC u32 search_on_register (const u32 in, const u32 p0);
DECLSPEC u32 replace_on_register (const u32 in, const u32 r, const u32 p1);
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_replace (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len);
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_replace_class (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len);
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_purgechar (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len);
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_purgechar_class (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len);
DECLSPEC HC_INLINE_RP u32 rule_op_mangle_dupechar_first (MAYBE_UNUSED const u32 p0, MAYBE_UNUSED const u32 p1, MAYBE_UNUSED PRIVATE_AS u32 *buf0, MAYBE_UNUSED PRIVATE_AS u32 *buf1, const u32 in_len);

View File

@ -133,7 +133,7 @@
- Hardware Monitor: avoid sprintf in src/ext_iokit.c
- Help: show supported hash-modes only with -hh
- Makefile: prevent make failure with Apple Silicon in case of partial rebuild
- Rules: Extended the Purge (@) rule operation to support Classes
- Rules: Add support to character class rules
- Rules: Rename best64.rule to best66.rule and remove the unknown section from it
* changes v6.2.5 -> v6.2.6

View File

@ -25,7 +25,7 @@ Gabriele "matrix" Gristina <matrix@hashcat.net> (@gm4tr1x)
* Apple macOS port
* Apple Silicon support
* Universal binary on Apple Silicon
* Extended the Purge (@) rule operation to support Classes
* Add support to character class rules
* Hardware monitor initial code base and maintenance
* Test suite initial code base and maintenance
* Makefile initial code base

View File

@ -23,7 +23,7 @@
#define RULE_OP_MANGLE_OVERSTRIKE 'o' // overwrite with char X at pos N
#define RULE_OP_MANGLE_TRUNCATE_AT '\'' // cut the word at pos N
#define RULE_OP_MANGLE_REPLACE 's' // replace all chars X with char Y
#define RULE_OP_MANGLE_PURGECHAR '@' // purge all instances of char X (@X) or purge all instances of chars in class X (@?X)
#define RULE_OP_MANGLE_PURGECHAR '@' // purge all instances of char X
#define RULE_OP_MANGLE_DUPECHAR_FIRST 'z' // prepend first char of word to itself N times. ex: hello -> hhhello
#define RULE_OP_MANGLE_DUPECHAR_LAST 'Z' // append last char of word to itself N times. ex: hello -> hellooo
#define RULE_OP_MANGLE_DUPECHAR_ALL 'q' // duplicate all chars. ex: hello -> hheelllloo
@ -59,3 +59,18 @@
#define RULE_OP_REJECT_CONTAINS '%' // reject plains that contain char X less than N times
#define RULE_OP_REJECT_MEMORY 'Q' // reject plains that match the plain saved (see M), i.e. if unchanged
#define RULE_LAST_REJECTED_SAVED_POS 'p' // pos of the char last found with '/' or '%'
/* using character classes */
#define RULE_OP_CLASS_BASED '~'
#define RULE_OP_MANGLE_REPLACE_CLASS 0x01 // replace all instances of chars in class C with char Y, ~s?CY
#define RULE_OP_MANGLE_PURGECHAR_CLASS 0x02 // purge all instances of chars in class C, ~@?C
/* using character classes, with -j or -k only */
#define RULE_OP_REJECT_CONTAIN_CLASS 0x03 // reject plains that contain chars in class C, ~!?C
#define RULE_OP_REJECT_NOT_CONTAIN_CLASS 0x04 // reject plains that do not contain chars in class C, ~/?C
#define RULE_OP_REJECT_EQUAL_FIRST_CLASS 0x05 // reject plains that do not contain char in class C at first pos, ~(?C
#define RULE_OP_REJECT_EQUAL_LAST_CLASS 0x06 // reject plains that do not contain char in class C at last pos, ~)?C
#define RULE_OP_REJECT_EQUAL_AT_CLASS 0x07 // reject plains that do not contain char in class C at pos N, ~=N?C
#define RULE_OP_REJECT_CONTAINS_CLASS 0x08 // reject plains that contain char in class C less than N times, ~%N?C

View File

@ -331,7 +331,6 @@ typedef enum rule_functions
RULE_OP_MANGLE_TRUNCATE_AT = '\'',
RULE_OP_MANGLE_REPLACE = 's',
RULE_OP_MANGLE_PURGECHAR = '@',
RULE_OP_MANGLE_PURGECHAR_CLASS = 0x01,
RULE_OP_MANGLE_TOGGLECASE_REC = 'a',
RULE_OP_MANGLE_DUPECHAR_FIRST = 'z',
RULE_OP_MANGLE_DUPECHAR_LAST = 'Z',
@ -368,6 +367,17 @@ typedef enum rule_functions
RULE_OP_MANGLE_DUPEBLOCK_LAST = 'Y',
RULE_OP_MANGLE_TITLE = 'E',
/* using character classes */
RULE_OP_CLASS_BASED = '~',
RULE_OP_MANGLE_REPLACE_CLASS = 0x01,
RULE_OP_MANGLE_PURGECHAR_CLASS = 0x02,
RULE_OP_REJECT_CONTAIN_CLASS = 0x03,
RULE_OP_REJECT_NOT_CONTAIN_CLASS = 0x04,
RULE_OP_REJECT_EQUAL_FIRST_CLASS = 0x05,
RULE_OP_REJECT_EQUAL_LAST_CLASS = 0x06,
RULE_OP_REJECT_EQUAL_AT_CLASS = 0x07,
RULE_OP_REJECT_CONTAINS_CLASS = 0x08,
} rule_functions_t;
typedef enum salt_type

120
src/rp.c
View File

@ -388,42 +388,6 @@ int cpu_rule_to_kernel_rule (char *rule_buf, u32 rule_len, kernel_rule_t *rule)
break;
case RULE_OP_MANGLE_PURGECHAR:
if ((rule_pos + 1) < rule_len && rule_buf[rule_pos+1] == '?')
{
if ((rule_pos + 2) == rule_len)
{
SET_NAME (rule, rule_buf[rule_pos]);
SET_P0 (rule, rule_buf[rule_pos]);
break;
}
switch (rule_buf[rule_pos+2]) {
case '\'':
SET_NAME (rule, rule_buf[rule_pos]);
SET_P0 (rule, rule_buf[rule_pos]);
break;
case ' ':
case '?':
SET_NAME (rule, rule_buf[rule_pos]);
SET_P0 (rule, rule_buf[rule_pos]);
INCR_POS;
break;
case 'l':
case 'u':
case 'd':
case 'h':
case 'H':
case 's':
SET_NAME (rule, RULE_OP_MANGLE_PURGECHAR_CLASS);
SET_P0 (rule, rule_buf[rule_pos+1]);
INCR_POS;
break;
default :
return -1;
}
break;
}
SET_NAME (rule, rule_buf[rule_pos]);
SET_P0 (rule, rule_buf[rule_pos]);
break;
@ -514,6 +478,68 @@ int cpu_rule_to_kernel_rule (char *rule_buf, u32 rule_len, kernel_rule_t *rule)
SET_P1 (rule, rule_buf[rule_pos]);
break;
case RULE_OP_CLASS_BASED: // ~
switch (rule_buf[rule_pos+1])
{
case RULE_OP_MANGLE_REPLACE: // ~s?CY
SET_NAME (rule, RULE_OP_MANGLE_REPLACE_CLASS);
INCR_POS;
INCR_POS;
SET_P0 (rule, rule_buf[rule_pos]);
SET_P1 (rule, rule_buf[rule_pos]);
break;
case RULE_OP_MANGLE_PURGECHAR: // ~@?C
SET_NAME (rule, RULE_OP_MANGLE_PURGECHAR_CLASS);
INCR_POS;
INCR_POS;
SET_P0 (rule, rule_buf[rule_pos]);
break;
/*
case '!': // ~!?C
SET_NAME (rule, RULE_OP_REJECT_CONTAIN_CLASS);
INCR_POS;
INCR_POS;
SET_P0 (rule, rule_buf[rule_pos]);
break;
case '/': // ~/?C
SET_NAME (rule, RULE_OP_REJECT_NOT_CONTAIN_CLASS);
INCR_POS;
INCR_POS;
SET_P0 (rule, rule_buf[rule_pos]);
break;
case '(': // ~(?C
SET_NAME (rule, RULE_OP_REJECT_EQUAL_FIRST_CLASS);
INCR_POS;
INCR_POS;
SET_P0 (rule, rule_buf[rule_pos]);
break;
case '(': // ~)?C
SET_NAME (rule, RULE_OP_REJECT_EQUAL_LAST_CLASS);
INCR_POS;
INCR_POS;
SET_P0 (rule, rule_buf[rule_pos]);
break;
case '=': // ~=N?C
SET_NAME (rule, RULE_OP_REJECT_EQUAL_AT_CLASS);
INCR_POS;
SET_P0 (rule, rule_buf[rule_pos]);
INCR_POS;
SET_P1 (rule, rule_buf[rule_pos]);
break;
case '%': // ~%N?C
SET_NAME (rule, RULE_OP_REJECT_CONTAINS_CLASS);
INCR_POS;
SET_P0 (rule, rule_buf[rule_pos]);
INCR_POS;
SET_P1 (rule, rule_buf[rule_pos]);
break;
*/
default:
return -1;
}
break;
default:
return -1;
}
@ -655,13 +681,6 @@ int kernel_rule_to_cpu_rule (char *rule_buf, kernel_rule_t *rule)
case RULE_OP_MANGLE_PURGECHAR:
rule_buf[rule_pos] = rule_cmd;
GET_P0 (rule);
if (rule_buf[rule_pos] == '?') rule_buf[++rule_pos] = '?'; // force @??
break;
case RULE_OP_MANGLE_PURGECHAR_CLASS:
rule_buf[rule_pos++] = RULE_OP_MANGLE_PURGECHAR;
rule_buf[rule_pos] = '?';
GET_P0 (rule);
break;
case RULE_OP_MANGLE_TOGGLECASE_REC:
@ -750,6 +769,21 @@ int kernel_rule_to_cpu_rule (char *rule_buf, kernel_rule_t *rule)
GET_P1 (rule);
break;
case RULE_OP_MANGLE_REPLACE_CLASS:
rule_buf[rule_pos++] = RULE_OP_CLASS_BASED;
rule_buf[rule_pos++] = RULE_OP_MANGLE_REPLACE;
rule_buf[rule_pos] = '?';
GET_P0 (rule);
GET_P1 (rule);
break;
case RULE_OP_MANGLE_PURGECHAR_CLASS:
rule_buf[rule_pos++] = RULE_OP_CLASS_BASED;
rule_buf[rule_pos++] = RULE_OP_MANGLE_PURGECHAR;
rule_buf[rule_pos] = '?';
GET_P0 (rule);
break;
case 0:
if (rule_pos == 0) return -1;
return rule_pos - 1;

View File

@ -329,6 +329,102 @@ static int mangle_replace (char arr[RP_PASSWORD_SIZE], int arr_len, char oldc, c
return (arr_len);
}
static int mangle_replace_class_l (char arr[RP_PASSWORD_SIZE], int arr_len, char newc)
{
int arr_pos;
for (arr_pos = 0; arr_pos < arr_len; arr_pos++)
{
if (!class_lower (arr[arr_pos])) continue;
arr[arr_pos] = newc;
}
return (arr_len);
}
static int mangle_replace_class_u (char arr[RP_PASSWORD_SIZE], int arr_len, char newc)
{
int arr_pos;
for (arr_pos = 0; arr_pos < arr_len; arr_pos++)
{
if (!class_upper (arr[arr_pos])) continue;
arr[arr_pos] = newc;
}
return (arr_len);
}
static int mangle_replace_class_d (char arr[RP_PASSWORD_SIZE], int arr_len, char newc)
{
int arr_pos;
for (arr_pos = 0; arr_pos < arr_len; arr_pos++)
{
if (!class_num (arr[arr_pos])) continue;
arr[arr_pos] = newc;
}
return (arr_len);
}
static int mangle_replace_class_lh (char arr[RP_PASSWORD_SIZE], int arr_len, char newc)
{
int arr_pos;
for (arr_pos = 0; arr_pos < arr_len; arr_pos++)
{
if (!class_lower_hex (arr[arr_pos])) continue;
arr[arr_pos] = newc;
}
return (arr_len);
}
static int mangle_replace_class_uh (char arr[RP_PASSWORD_SIZE], int arr_len, char newc)
{
int arr_pos;
for (arr_pos = 0; arr_pos < arr_len; arr_pos++)
{
if (!class_upper_hex (arr[arr_pos])) continue;
arr[arr_pos] = newc;
}
return (arr_len);
}
static int mangle_replace_class_s (char arr[RP_PASSWORD_SIZE], int arr_len, char newc)
{
int arr_pos;
for (arr_pos = 0; arr_pos < arr_len; arr_pos++)
{
if (!class_sym (arr[arr_pos])) continue;
arr[arr_pos] = newc;
}
return (arr_len);
}
static int mangle_replace_class (char arr[RP_PASSWORD_SIZE], int arr_len, char oldc, char newc)
{
if (oldc == 'l') return mangle_replace_class_l (arr, arr_len, newc);
else if (oldc == 'u') return mangle_replace_class_u (arr, arr_len, newc);
else if (oldc == 'd') return mangle_replace_class_d (arr, arr_len, newc);
else if (oldc == 'h') return mangle_replace_class_lh (arr, arr_len, newc);
else if (oldc == 'H') return mangle_replace_class_uh (arr, arr_len, newc);
else if (oldc == 's') return mangle_replace_class_s (arr, arr_len, newc);
return (arr_len);
}
static int mangle_purgechar (char arr[RP_PASSWORD_SIZE], int arr_len, char c)
{
int arr_pos;
@ -630,6 +726,236 @@ static int mangle_title_sep (char arr[RP_PASSWORD_SIZE], int arr_len, char c)
return (arr_len);
}
static bool reject_contain_class_l (char arr[RP_PASSWORD_SIZE], int arr_len, int *pos_mem)
{
for (int arr_pos = 0; arr_pos < arr_len; arr_pos++)
{
if (class_lower (arr[arr_pos]))
{
*pos_mem = arr_pos;
return true;
}
}
return false;
}
static bool reject_contain_class_u (char arr[RP_PASSWORD_SIZE], int arr_len, int *pos_mem)
{
for (int arr_pos = 0; arr_pos < arr_len; arr_pos++)
{
if (class_upper (arr[arr_pos]))
{
*pos_mem = arr_pos;
return true;
}
}
return false;
}
static bool reject_contain_class_d (char arr[RP_PASSWORD_SIZE], int arr_len, int *pos_mem)
{
for (int arr_pos = 0; arr_pos < arr_len; arr_pos++)
{
if (class_num (arr[arr_pos]))
{
*pos_mem = arr_pos;
return true;
}
}
return false;
}
static bool reject_contain_class_lh (char arr[RP_PASSWORD_SIZE], int arr_len, int *pos_mem)
{
for (int arr_pos = 0; arr_pos < arr_len; arr_pos++)
{
if (class_lower_hex (arr[arr_pos]))
{
*pos_mem = arr_pos;
return true;
}
}
return false;
}
static bool reject_contain_class_uh (char arr[RP_PASSWORD_SIZE], int arr_len, int *pos_mem)
{
for (int arr_pos = 0; arr_pos < arr_len; arr_pos++)
{
if (class_upper_hex (arr[arr_pos]))
{
*pos_mem = arr_pos;
return true;
}
}
return false;
}
static bool reject_contain_class_s (char arr[RP_PASSWORD_SIZE], int arr_len, int *pos_mem)
{
for (int arr_pos = 0; arr_pos < arr_len; arr_pos++)
{
if (class_sym (arr[arr_pos]))
{
*pos_mem = arr_pos;
return true;
}
}
return false;
}
static bool reject_contain_class (char arr[RP_PASSWORD_SIZE], int arr_len, char c, int *pos_mem)
{
if (c == 'l') return reject_contain_class_l (arr, arr_len, pos_mem);
else if (c == 'u') return reject_contain_class_u (arr, arr_len, pos_mem);
else if (c == 'd') return reject_contain_class_d (arr, arr_len, pos_mem);
else if (c == 'h') return reject_contain_class_lh (arr, arr_len, pos_mem);
else if (c == 'H') return reject_contain_class_uh (arr, arr_len, pos_mem);
else if (c == 's') return reject_contain_class_s (arr, arr_len, pos_mem);
return false;
}
static bool reject_contain (char arr[RP_PASSWORD_SIZE], char c, int *pos_mem)
{
const char *match = strchr (arr, c);
if (match == NULL) return false;
*pos_mem = (int)(match - arr);
return true;
}
static bool reject_contains_class_l (char arr[RP_PASSWORD_SIZE], int arr_len, int upos, int *pos_mem)
{
int cnt = 0;
for (int arr_pos = 0; arr_pos < arr_len && cnt < upos; arr_pos++)
{
if (class_lower (arr[arr_pos]))
{
cnt++;
*pos_mem = arr_pos;
}
}
return (cnt < upos);
}
static bool reject_contains_class_u (char arr[RP_PASSWORD_SIZE], int arr_len, int upos, int *pos_mem)
{
int cnt = 0;
for (int arr_pos = 0; arr_pos < arr_len && cnt < upos; arr_pos++)
{
if (class_upper (arr[arr_pos]))
{
cnt++;
*pos_mem = arr_pos;
}
}
return (cnt < upos);
}
static bool reject_contains_class_d (char arr[RP_PASSWORD_SIZE], int arr_len, int upos, int *pos_mem)
{
int cnt = 0;
for (int arr_pos = 0; arr_pos < arr_len && cnt < upos; arr_pos++)
{
if (class_num (arr[arr_pos]))
{
cnt++;
*pos_mem = arr_pos;
}
}
return (cnt < upos);
}
static bool reject_contains_class_lh (char arr[RP_PASSWORD_SIZE], int arr_len, int upos, int *pos_mem)
{
int cnt = 0;
for (int arr_pos = 0; arr_pos < arr_len && cnt < upos; arr_pos++)
{
if (class_lower_hex (arr[arr_pos]))
{
cnt++;
*pos_mem = arr_pos;
}
}
return (cnt < upos);
}
static bool reject_contains_class_uh (char arr[RP_PASSWORD_SIZE], int arr_len, int upos, int *pos_mem)
{
int cnt = 0;
for (int arr_pos = 0; arr_pos < arr_len && cnt < upos; arr_pos++)
{
if (class_upper_hex (arr[arr_pos]))
{
cnt++;
*pos_mem = arr_pos;
}
}
return (cnt < upos);
}
static bool reject_contains_class_s (char arr[RP_PASSWORD_SIZE], int arr_len, int upos, int *pos_mem)
{
int cnt = 0;
for (int arr_pos = 0; arr_pos < arr_len && cnt < upos; arr_pos++)
{
if (class_sym (arr[arr_pos]))
{
cnt++;
*pos_mem = arr_pos;
}
}
return (cnt < upos);
}
static bool reject_contains_class (char arr[RP_PASSWORD_SIZE], int arr_len, char c, int upos, int *pos_mem)
{
if (c == 'l') return reject_contains_class_l (arr, arr_len, upos, pos_mem);
else if (c == 'u') return reject_contains_class_u (arr, arr_len, upos, pos_mem);
else if (c == 'd') return reject_contains_class_d (arr, arr_len, upos, pos_mem);
else if (c == 'h') return reject_contains_class_lh (arr, arr_len, upos, pos_mem);
else if (c == 'H') return reject_contains_class_uh (arr, arr_len, upos, pos_mem);
else if (c == 's') return reject_contains_class_s (arr, arr_len, upos, pos_mem);
return false;
}
static bool reject_contains (const char arr[RP_PASSWORD_SIZE], int arr_len, char c, int upos, int *pos_mem)
{
int cnt = 0;
for (int arr_pos = 0; arr_pos < arr_len && cnt < upos; arr_pos++)
{
if (arr[arr_pos] == c)
{
cnt++;
*pos_mem = arr_pos;
}
}
return (cnt < upos);
}
int _old_apply_rule (const char *rule, int rule_len, char in[RP_PASSWORD_SIZE], int in_len, char out[RP_PASSWORD_SIZE])
{
char mem[RP_PASSWORD_SIZE] = { 0 };
@ -819,33 +1145,6 @@ int _old_apply_rule (const char *rule, int rule_len, char in[RP_PASSWORD_SIZE],
case RULE_OP_MANGLE_PURGECHAR:
NEXT_RULEPOS (rule_pos);
if (rule_new[rule_pos] == '?')
{
if ((rule_pos + 1) == rule_len_new || ((rule_pos + 1) < rule_len_new && rule_new[rule_pos+1] == '\''))
{
out_len = mangle_purgechar (out, out_len, rule_new[rule_pos]);
break;
}
NEXT_RULEPOS (rule_pos);
switch (rule_new[rule_pos])
{
case ' ': out_len = mangle_purgechar (out, out_len, rule_new[rule_pos-1]); break;
case '?': out_len = mangle_purgechar (out, out_len, rule_new[rule_pos]); break;
case 'l':
case 'u':
case 'd':
case 'h':
case 'H':
case 's': out_len = mangle_purgechar_class (out, out_len, rule_new[rule_pos]); break;
default : HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
}
break;
}
out_len = mangle_purgechar (out, out_len, rule_new[rule_pos]);
break;
@ -993,22 +1292,12 @@ int _old_apply_rule (const char *rule, int rule_len, char in[RP_PASSWORD_SIZE],
case RULE_OP_REJECT_CONTAIN:
NEXT_RULEPOS (rule_pos);
if (strchr (out, rule_new[rule_pos]) != NULL) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
if (reject_contain (out, rule_new[rule_pos], &pos_mem)) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case RULE_OP_REJECT_NOT_CONTAIN:
NEXT_RULEPOS (rule_pos);
{
const char *match = strchr (out, rule_new[rule_pos]);
if (match != NULL)
{
pos_mem = (int)(match - out);
}
else
{
HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
}
}
if (!reject_contain (out, rule_new[rule_pos], &pos_mem)) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case RULE_OP_REJECT_EQUAL_FIRST:
@ -1034,23 +1323,248 @@ int _old_apply_rule (const char *rule, int rule_len, char in[RP_PASSWORD_SIZE],
NEXT_RPTOI (rule_new, rule_pos, upos);
if ((upos + 1) > out_len) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
NEXT_RULEPOS (rule_pos);
int c; int cnt;
for (c = 0, cnt = 0; c < out_len && cnt < upos; c++)
{
if (out[c] == rule_new[rule_pos])
{
cnt++;
pos_mem = c;
}
}
if (cnt < upos) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
if (reject_contains (out, out_len, rule_new[rule_pos], upos, &pos_mem)) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case RULE_OP_REJECT_MEMORY:
if ((out_len == mem_len) && (memcmp (out, mem, out_len) == 0)) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case RULE_OP_CLASS_BASED:
NEXT_RULEPOS (rule_pos);
switch (rule_new[rule_pos])
{
case RULE_OP_MANGLE_REPLACE: // ~s?CY
NEXT_RULEPOS (rule_pos);
if (rule_new[rule_pos] != '?') HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
NEXT_RULEPOS (rule_pos);
switch (rule_new[rule_pos])
{
case '?':
NEXT_RULEPOS (rule_pos);
out_len = mangle_replace (out, out_len, rule_new[rule_pos - 1], rule_new[rule_pos]);
break;
case 'l':
case 'u':
case 'd':
case 'h':
case 'H':
case 's':
NEXT_RULEPOS (rule_pos);
out_len = mangle_replace_class (out, out_len, rule_new[rule_pos - 1], rule_new[rule_pos]);
break;
default :
HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
}
break;
case RULE_OP_MANGLE_PURGECHAR: // ~@?C
NEXT_RULEPOS (rule_pos);
if (rule_new[rule_pos] != '?') HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
NEXT_RULEPOS (rule_pos);
switch (rule_new[rule_pos])
{
case '?':
out_len = mangle_purgechar (out, out_len, rule_new[rule_pos]);
break;
case 'l':
case 'u':
case 'd':
case 'h':
case 'H':
case 's':
out_len = mangle_purgechar_class (out, out_len, rule_new[rule_pos]);
break;
default :
HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
}
break;
case RULE_OP_REJECT_CONTAIN: // ~!?C
NEXT_RULEPOS (rule_pos);
if (rule_new[rule_pos] != '?') HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
NEXT_RULEPOS (rule_pos);
switch (rule_new[rule_pos])
{
case '?':
if (reject_contain (out, rule_new[rule_pos], &pos_mem)) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'l':
case 'u':
case 'd':
case 'h':
case 'H':
case 's':
if (reject_contain_class (out, out_len, rule_new[rule_pos], &pos_mem)) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
default :
HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
}
break;
case RULE_OP_REJECT_NOT_CONTAIN: // ~/?C
NEXT_RULEPOS (rule_pos);
if (rule_new[rule_pos] != '?') HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
NEXT_RULEPOS (rule_pos);
switch (rule_new[rule_pos])
{
case '?':
if (!reject_contain (out, rule_new[rule_pos], &pos_mem)) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'l':
case 'u':
case 'd':
case 'h':
case 'H':
case 's':
if (!reject_contain_class (out, out_len, rule_new[rule_pos], &pos_mem)) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
default :
HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
}
break;
case RULE_OP_REJECT_EQUAL_FIRST: // ~(?C
NEXT_RULEPOS (rule_pos);
if (rule_new[rule_pos] != '?') HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
NEXT_RULEPOS (rule_pos);
switch (rule_new[rule_pos])
{
case '?':
if (out[0] != rule_new[rule_pos]) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'l':
if (!class_lower (out[0])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'u':
if (!class_upper (out[0])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'd':
if (!class_num (out[0])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'h':
if (!class_lower_hex (out[0])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'H':
if (!class_upper_hex (out[0])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 's':
if (!class_sym (out[0])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
default :
HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
}
break;
case RULE_OP_REJECT_EQUAL_LAST: // ~)?C
NEXT_RULEPOS (rule_pos);
if (rule_new[rule_pos] != '?') HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
NEXT_RULEPOS (rule_pos);
switch (rule_new[rule_pos])
{
case '?':
if (out[out_len - 1] != rule_new[rule_pos]) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'l':
if (!class_lower (out[out_len - 1])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'u':
if (!class_upper (out[out_len - 1])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'd':
if (!class_num (out[out_len - 1])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'h':
if (!class_lower_hex (out[out_len - 1])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'H':
if (!class_upper_hex (out[out_len - 1])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 's':
if (!class_sym (out[out_len - 1])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
default :
HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
}
break;
case RULE_OP_REJECT_EQUAL_AT: // ~=N?C
NEXT_RULEPOS (rule_pos);
NEXT_RPTOI (rule_new, rule_pos, upos);
if ((upos + 1) > out_len) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
NEXT_RULEPOS (rule_pos);
if (rule_new[rule_pos] != '?') HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
NEXT_RULEPOS (rule_pos);
switch (rule_new[rule_pos])
{
case '?':
if (out[upos] != rule_new[rule_pos]) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'l':
if (!class_lower (out[upos])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'u':
if (!class_upper (out[upos])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'd':
if (!class_num (out[upos])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'h':
if (!class_lower_hex (out[upos])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'H':
if (!class_upper_hex (out[upos])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 's':
if (!class_sym (out[upos])) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
default :
HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
}
break;
case RULE_OP_REJECT_CONTAINS: // ~%N?C
NEXT_RULEPOS (rule_pos);
NEXT_RPTOI (rule_new, rule_pos, upos);
if ((upos + 1) > out_len) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
NEXT_RULEPOS (rule_pos);
if (rule_new[rule_pos] != '?') HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
NEXT_RULEPOS (rule_pos);
switch (rule_new[rule_pos])
{
case '?':
if (reject_contains (out, out_len, rule_new[rule_pos], upos, &pos_mem)) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
case 'l':
case 'u':
case 'd':
case 'h':
case 'H':
case 's':
if (reject_contains_class (out, out_len, rule_new[rule_pos], upos, &pos_mem)) HCFREE_AND_RETURN (RULE_RC_REJECT_ERROR);
break;
default :
HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
}
break;
default:
HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
}
break;
default:
HCFREE_AND_RETURN (RULE_RC_SYNTAX_ERROR);
}