1 /* 2 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * This program is copyright Alec Muffett 1993. The author disclaims all 8 * responsibility or liability with respect to it's usage or its effect 9 * upon hardware or computer systems, and maintains copyright as set out 10 * in the "LICENCE" document which accompanies distributions of Crack v4.0 11 * and upwards. 12 */ 13 14 #include "packer.h" 15 16 17 #define RULE_NOOP ':' 18 #define RULE_PREPEND '^' 19 #define RULE_APPEND '$' 20 #define RULE_REVERSE 'r' 21 #define RULE_UPPERCASE 'u' 22 #define RULE_LOWERCASE 'l' 23 #define RULE_PLURALISE 'p' 24 #define RULE_CAPITALISE 'c' 25 #define RULE_DUPLICATE 'd' 26 #define RULE_REFLECT 'f' 27 #define RULE_SUBSTITUTE 's' 28 #define RULE_MATCH '/' 29 #define RULE_NOT '!' 30 #define RULE_LT '<' 31 #define RULE_GT '>' 32 #define RULE_EXTRACT 'x' 33 #define RULE_OVERSTRIKE 'o' 34 #define RULE_INSERT 'i' 35 #define RULE_EQUALS '=' 36 #define RULE_PURGE '@' 37 #define RULE_CLASS '?' /* class rule? socialist ethic in cracker? */ 38 #define RULE_DFIRST '[' 39 #define RULE_DLAST ']' 40 #define RULE_MFIRST '(' 41 #define RULE_MLAST ')' 42 43 int 44 Suffix(char *myword, char *suffix) 45 { 46 register int i; 47 register int j; 48 49 i = strlen(myword); 50 j = strlen(suffix); 51 52 if (i > j) { 53 return (STRCMP((myword + i - j), suffix)); 54 } else { 55 return (-1); 56 } 57 } 58 59 char * 60 Reverse(register char *str) /* return a pointer to a reversal */ 61 { 62 register int i; 63 register int j; 64 static char area[PATH_MAX]; 65 66 j = i = strlen(str); 67 while (*str) { 68 area[--i] = *str++; 69 } 70 area[j] = '\0'; 71 return (area); 72 } 73 74 char * 75 Uppercase(register char *str) /* return a pointer to an uppercase */ 76 { 77 register char *ptr; 78 static char area[PATH_MAX]; 79 80 ptr = area; 81 while (*str) { 82 *(ptr++) = CRACK_TOUPPER(*str); 83 str++; 84 } 85 *ptr = '\0'; 86 87 return (area); 88 } 89 90 char * 91 Lowercase(register char *str) /* return a pointer to an lowercase */ 92 { 93 register char *ptr; 94 static char area[PATH_MAX]; 95 96 ptr = area; 97 while (*str) { 98 *(ptr++) = CRACK_TOLOWER(*str); 99 str++; 100 } 101 *ptr = '\0'; 102 103 return (area); 104 } 105 106 char * 107 Capitalise(register char *str) /* return a pointer to an capitalised */ 108 { 109 register char *ptr; 110 static char area[PATH_MAX]; 111 112 ptr = area; 113 114 while (*str) { 115 *(ptr++) = CRACK_TOLOWER(*str); 116 str++; 117 } 118 119 *ptr = '\0'; 120 area[0] = CRACK_TOUPPER(area[0]); 121 return (area); 122 } 123 124 char * 125 Pluralise(register char *string) /* returns a pointer to a plural */ 126 { 127 register int length; 128 static char area[PATH_MAX]; 129 130 length = strlen(string); 131 (void) strlcpy(area, string, PATH_MAX); 132 133 if (!Suffix(string, "ch") || 134 !Suffix(string, "ex") || 135 !Suffix(string, "ix") || 136 !Suffix(string, "sh") || 137 !Suffix(string, "ss")) { 138 /* bench -> benches */ 139 (void) strcat(area, "es"); 140 } else if (length > 2 && string[length - 1] == 'y') { 141 if (strchr("aeiou", string[length - 2])) { 142 /* alloy -> alloys */ 143 (void) strcat(area, "s"); 144 } else { 145 /* gully -> gullies */ 146 (void) strcpy(area + length - 1, "ies"); 147 } 148 } else if (string[length - 1] == 's') { 149 /* bias -> biases */ 150 (void) strcat(area, "es"); 151 } else { 152 /* catchall */ 153 (void) strcat(area, "s"); 154 } 155 156 return (area); 157 } 158 159 char * 160 Substitute(register char *string, register char old, 161 register char new) /* returns pointer to a swapped about copy */ 162 { 163 register char *ptr; 164 static char area[PATH_MAX]; 165 166 ptr = area; 167 while (*string) { 168 *(ptr++) = (*string == old ? new : *string); 169 string++; 170 } 171 *ptr = '\0'; 172 return (area); 173 } 174 175 /* returns pointer to a purged copy */ 176 char * 177 Purge(register char *string, register char target) 178 { 179 register char *ptr; 180 static char area[PATH_MAX]; 181 ptr = area; 182 while (*string) { 183 if (*string != target) { 184 *(ptr++) = *string; 185 } 186 string++; 187 } 188 *ptr = '\0'; 189 return (area); 190 } 191 /* -------- CHARACTER CLASSES START HERE -------- */ 192 193 /* 194 * this function takes two inputs, a class identifier and a character, and 195 * returns non-null if the given character is a member of the class, based 196 * upon restrictions set out below 197 */ 198 199 int 200 MatchClass(register char class, register char input) 201 { 202 register char c; 203 register int retval; 204 205 retval = 0; 206 207 switch (class) { 208 /* ESCAPE */ 209 210 case '?': /* ?? -> ? */ 211 if (input == '?') { 212 retval = 1; 213 } 214 break; 215 216 /* ILLOGICAL GROUPINGS (ie: not in ctype.h) */ 217 218 case 'V': 219 case 'v': /* vowels */ 220 c = CRACK_TOLOWER(input); 221 if (strchr("aeiou", c)) { 222 retval = 1; 223 } 224 break; 225 226 case 'C': 227 case 'c': /* consonants */ 228 c = CRACK_TOLOWER(input); 229 if (strchr("bcdfghjklmnpqrstvwxyz", c)) { 230 retval = 1; 231 } 232 break; 233 234 case 'W': 235 case 'w': /* whitespace */ 236 if (strchr("\t ", input)) { 237 retval = 1; 238 } 239 break; 240 241 case 'P': 242 case 'p': /* punctuation */ 243 if (strchr(".`,:;'!?\"", input)) { 244 retval = 1; 245 } 246 break; 247 248 case 'S': 249 case 's': /* symbols */ 250 if (strchr("$%%^&*()-_+=|\\[]{}#@/~", input)) { 251 retval = 1; 252 } 253 break; 254 255 /* LOGICAL GROUPINGS */ 256 257 case 'L': 258 case 'l': /* lowercase */ 259 if (islower(input)) { 260 retval = 1; 261 } 262 break; 263 264 case 'U': 265 case 'u': /* uppercase */ 266 if (isupper(input)) { 267 retval = 1; 268 } 269 break; 270 271 case 'A': 272 case 'a': /* alphabetic */ 273 if (isalpha(input)) { 274 retval = 1; 275 } 276 break; 277 278 case 'X': 279 case 'x': /* alphanumeric */ 280 if (isalnum(input)) { 281 retval = 1; 282 } 283 break; 284 285 case 'D': 286 case 'd': /* digits */ 287 if (isdigit(input)) { 288 retval = 1; 289 } 290 break; 291 } 292 293 if (isupper(class)) { 294 return (!retval); 295 } 296 return (retval); 297 } 298 299 char * 300 PolyStrchr(register char *string, register char class) 301 { 302 while (*string) { 303 if (MatchClass(class, *string)) { 304 return (string); 305 } 306 string++; 307 } 308 return ((char *)0); 309 } 310 311 /* returns pointer to a swapped about copy */ 312 char * 313 PolySubst(register char *string, register char class, register char new) 314 { 315 register char *ptr; 316 static char area[PATH_MAX]; 317 318 ptr = area; 319 while (*string) { 320 *(ptr++) = (MatchClass(class, *string) ? new : *string); 321 string++; 322 } 323 *ptr = '\0'; 324 return (area); 325 } 326 327 /* returns pointer to a purged copy */ 328 char * 329 PolyPurge(register char *string, register char class) 330 { 331 register char *ptr; 332 static char area[PATH_MAX]; 333 334 ptr = area; 335 while (*string) { 336 if (!MatchClass(class, *string)) { 337 *(ptr++) = *string; 338 } 339 string++; 340 } 341 *ptr = '\0'; 342 return (area); 343 } 344 /* -------- BACK TO NORMALITY -------- */ 345 346 int 347 Char2Int(char character) 348 { 349 if (isdigit(character)) { 350 return (character - '0'); 351 } else if (islower(character)) { 352 return (character - 'a' + 10); 353 } else if (isupper(character)) { 354 return (character - 'A' + 10); 355 } 356 return (-1); 357 } 358 359 /* returns a pointer to a controlled Mangle */ 360 char * 361 Mangle(char *input, char *control) 362 { 363 int limit; 364 register char *ptr; 365 static char area[PATH_MAX]; 366 char area2[PATH_MAX]; 367 368 area[0] = '\0'; 369 (void) strlcpy(area, input, PATH_MAX); 370 371 for (ptr = control; *ptr; ptr++) { 372 switch (*ptr) { 373 case RULE_NOOP: 374 break; 375 case RULE_REVERSE: 376 (void) strlcpy(area, Reverse(area), PATH_MAX); 377 break; 378 case RULE_UPPERCASE: 379 (void) strlcpy(area, Uppercase(area), PATH_MAX); 380 break; 381 case RULE_LOWERCASE: 382 (void) strlcpy(area, Lowercase(area), PATH_MAX); 383 break; 384 case RULE_CAPITALISE: 385 (void) strlcpy(area, Capitalise(area), 386 PATH_MAX); 387 break; 388 case RULE_PLURALISE: 389 (void) strlcpy(area, Pluralise(area), PATH_MAX); 390 break; 391 case RULE_REFLECT: 392 (void) strlcat(area, Reverse(area), PATH_MAX); 393 break; 394 case RULE_DUPLICATE: 395 (void) strlcpy(area2, area, PATH_MAX); 396 (void) strlcat(area, area2, PATH_MAX); 397 break; 398 case RULE_GT: 399 if (!ptr[1]) { 400 return ((char *)0); 401 } else { 402 limit = Char2Int(*(++ptr)); 403 if (limit < 0) { 404 return ((char *)0); 405 } 406 if (strlen(area) <= limit) { 407 return ((char *)0); 408 } 409 } 410 break; 411 case RULE_LT: 412 if (!ptr[1]) { 413 return ((char *)0); 414 } else { 415 limit = Char2Int(*(++ptr)); 416 if (limit < 0) { 417 return ((char *)0); 418 } 419 if (strlen(area) >= limit) { 420 return ((char *)0); 421 } 422 } 423 break; 424 case RULE_PREPEND: 425 if (!ptr[1]) { 426 return ((char *)0); 427 } else { 428 area2[0] = *(++ptr); 429 (void) strlcpy(area2 + 1, area, 430 PATH_MAX); 431 (void) strlcpy(area, area2, PATH_MAX); 432 } 433 break; 434 case RULE_APPEND: 435 if (!ptr[1]) { 436 return ((char *)0); 437 } else { 438 register char *string; 439 440 string = area; 441 while (*(string++)); 442 string[-1] = *(++ptr); 443 *string = '\0'; 444 } 445 break; 446 case RULE_EXTRACT: 447 if (!ptr[1] || !ptr[2]) { 448 return ((char *)0); 449 } else { 450 register int i; 451 int start; 452 int length; 453 454 start = Char2Int(*(++ptr)); 455 length = Char2Int(*(++ptr)); 456 if (start < 0 || length < 0) { 457 return ((char *)0); 458 } 459 (void) strlcpy(area2, area, PATH_MAX); 460 for (i = 0; length-- && 461 area2[start + i]; i++) { 462 area[i] = area2[start + i]; 463 } 464 /* cant use strncpy()-no trailing NUL */ 465 area[i] = '\0'; 466 } 467 break; 468 case RULE_OVERSTRIKE: 469 if (!ptr[1] || !ptr[2]) { 470 return ((char *)0); 471 } else { 472 register int i; 473 474 i = Char2Int(*(++ptr)); 475 if (i < 0) { 476 return ((char *)0); 477 } else { 478 ++ptr; 479 if (area[i]) { 480 area[i] = *ptr; 481 } 482 } 483 } 484 break; 485 case RULE_INSERT: 486 if (!ptr[1] || !ptr[2]) { 487 return ((char *)0); 488 } else { 489 register int i; 490 register char *p1; 491 register char *p2; 492 493 i = Char2Int(*(++ptr)); 494 if (i < 0) { 495 return ((char *)0); 496 } 497 p1 = area; 498 p2 = area2; 499 while (i && *p1) { 500 i--; 501 *(p2++) = *(p1++); 502 } 503 *(p2++) = *(++ptr); 504 (void) strlcpy(p2, p1, PATH_MAX); 505 (void) strlcpy(area, area2, PATH_MAX); 506 } 507 break; 508 /* THE FOLLOWING RULES REQUIRE CLASS MATCHING */ 509 510 case RULE_PURGE: /* @x or @?c */ 511 if (!ptr[1] || (ptr[1] == 512 RULE_CLASS && !ptr[2])) { 513 return ((char *)0); 514 } else if (ptr[1] != RULE_CLASS) { 515 (void) strlcpy(area, Purge(area, 516 *(++ptr)), PATH_MAX); 517 } else { 518 (void) strlcpy(area, PolyPurge(area, 519 ptr[2]), PATH_MAX); 520 ptr += 2; 521 } 522 break; 523 case RULE_SUBSTITUTE: /* sxy || s?cy */ 524 if (!ptr[1] || !ptr[2] || 525 (ptr[1] == RULE_CLASS && !ptr[3])) { 526 return ((char *)0); 527 } else if (ptr[1] != RULE_CLASS) { 528 ptr += 2; 529 } else { 530 (void) strlcpy(area, PolySubst(area, 531 ptr[2], ptr[3]), PATH_MAX); 532 ptr += 3; 533 } 534 break; 535 case RULE_MATCH: /* /x || /?c */ 536 if (!ptr[1] || 537 (ptr[1] == RULE_CLASS && !ptr[2])) { 538 return ((char *)0); 539 } else if (ptr[1] != RULE_CLASS) { 540 if (!strchr(area, *(++ptr))) { 541 return ((char *)0); 542 } 543 } else { 544 if (!PolyStrchr(area, ptr[2])) { 545 return ((char *)0); 546 } 547 ptr += 2; 548 } 549 break; 550 case RULE_NOT: /* !x || !?c */ 551 if (!ptr[1] || 552 (ptr[1] == RULE_CLASS && !ptr[2])) { 553 return ((char *)0); 554 } else if (ptr[1] != RULE_CLASS) { 555 if (strchr(area, *(++ptr))) { 556 return ((char *)0); 557 } 558 } else { 559 if (PolyStrchr(area, ptr[2])) { 560 return ((char *)0); 561 } 562 ptr += 2; 563 } 564 break; 565 /* 566 * alternative use for a boomerang, number 1: a standard throwing 567 * boomerang is an ideal thing to use to tuck the sheets under 568 * the mattress when making your bed. The streamlined shape of 569 * the boomerang allows it to slip easily 'twixt mattress and 570 * bedframe, and it's curve makes it very easy to hook sheets 571 * into the gap. 572 */ 573 574 case RULE_EQUALS: /* =nx || =n?c */ 575 if (!ptr[1] || !ptr[2] || 576 (ptr[2] == RULE_CLASS && !ptr[3])) { 577 return ((char *)0); 578 } else { 579 register int i; 580 581 if ((i = Char2Int(ptr[1])) < 0) { 582 return ((char *)0); 583 } 584 if (ptr[2] != RULE_CLASS) { 585 ptr += 2; 586 if (area[i] != *ptr) { 587 return ((char *)0); 588 } 589 } else { 590 ptr += 3; 591 if (!MatchClass(*ptr, 592 area[i])) { 593 return ((char *)0); 594 } 595 } 596 } 597 break; 598 599 case RULE_DFIRST: 600 if (area[0]) { 601 register int i; 602 603 for (i = 1; area[i]; i++) { 604 area[i - 1] = area[i]; 605 } 606 area[i - 1] = '\0'; 607 } 608 break; 609 610 case RULE_DLAST: 611 if (area[0]) { 612 register int i; 613 614 for (i = 1; area[i]; i++); 615 area[i - 1] = '\0'; 616 } 617 break; 618 619 case RULE_MFIRST: 620 if (!ptr[1] || 621 (ptr[1] == RULE_CLASS && !ptr[2])) { 622 return ((char *)0); 623 } else { 624 if (ptr[1] != RULE_CLASS) { 625 ptr++; 626 if (area[0] != *ptr) { 627 return ((char *)0); 628 } 629 } else { 630 ptr += 2; 631 if (!MatchClass(*ptr, 632 area[0])) { 633 return ((char *)0); 634 } 635 } 636 } 637 break; 638 case RULE_MLAST: 639 if (!ptr[1] || 640 (ptr[1] == RULE_CLASS && !ptr[2])) { 641 return ((char *)0); 642 } else { 643 register int i; 644 645 for (i = 0; area[i]; i++); 646 647 if (i > 0) { 648 i--; 649 } else { 650 return ((char *)0); 651 } 652 if (ptr[1] != RULE_CLASS) { 653 ptr++; 654 if (area[i] != *ptr) { 655 return ((char *)0); 656 } 657 } else { 658 ptr += 2; 659 if (!MatchClass(*ptr, 660 area[i])) { 661 return ((char *)0); 662 } 663 } 664 } 665 break; 666 } 667 } 668 if (!area[0]) { /* have we deweted de poor widdle fing away? */ 669 return ((char *)0); 670 } 671 return (area); 672 } 673 /* 674 * int 675 * PMatch(register char *control, register char *string) 676 * { 677 * while (*string && *control) { 678 * if (!MatchClass(*control, *string)) { 679 * return (0); 680 * } 681 * 682 * string++; 683 * control++; 684 * } 685 * 686 * if (*string || *control) { 687 * return (0); 688 * } 689 * 690 * return (1); 691 * } 692 */ 693