obscure.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Copyright 1989 - 1994, Julianne Frances Haugh <jockgrrl@austin.rr.com>
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of Julianne F. Haugh nor the names of its contributors
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY JULIE HAUGH AND CONTRIBUTORS ``AS IS'' AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21. * ARE DISCLAIMED. IN NO EVENT SHALL JULIE HAUGH OR CONTRIBUTORS BE LIABLE
  22. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. */
  30. /*
  31. * This version of obscure.c contains modifications to support "cracklib"
  32. * by Alec Muffet (alec.muffett@uk.sun.com). You must obtain the Cracklib
  33. * library source code for this function to operate.
  34. */
  35. #include <stdlib.h>
  36. #include <stdio.h>
  37. #include <string.h>
  38. #include <ctype.h>
  39. #include "libbb.h"
  40. /*
  41. * can't be a palindrome - like `R A D A R' or `M A D A M'
  42. */
  43. static int palindrome(const char *newval)
  44. {
  45. int i, j;
  46. i = strlen(newval);
  47. for (j = 0; j < i; j++)
  48. if (newval[i - j - 1] != newval[j])
  49. return 0;
  50. return 1;
  51. }
  52. /*
  53. * more than half of the characters are different ones.
  54. */
  55. static int similiar(const char *old, const char *newval)
  56. {
  57. int i, j;
  58. for (i = j = 0; newval[i] && old[i]; i++)
  59. if (strchr(newval, old[i]))
  60. j++;
  61. if (i >= j * 2)
  62. return 0;
  63. return 1;
  64. }
  65. /*
  66. * a nice mix of characters.
  67. */
  68. static int simple(const char *newval)
  69. {
  70. int digits = 0;
  71. int uppers = 0;
  72. int lowers = 0;
  73. int others = 0;
  74. int c;
  75. int size;
  76. int i;
  77. for (i = 0; (c = *newval++) != 0; i++) {
  78. if (isdigit(c))
  79. digits = c;
  80. else if (isupper(c))
  81. uppers = c;
  82. else if (islower(c))
  83. lowers = c;
  84. else
  85. others = c;
  86. }
  87. /*
  88. * The scam is this - a password of only one character type
  89. * must be 8 letters long. Two types, 7, and so on.
  90. */
  91. size = 9;
  92. if (digits)
  93. size--;
  94. if (uppers)
  95. size--;
  96. if (lowers)
  97. size--;
  98. if (others)
  99. size--;
  100. if (size <= i)
  101. return 0;
  102. return 1;
  103. }
  104. static char *str_lower(char *string)
  105. {
  106. char *cp;
  107. for (cp = string; *cp; cp++)
  108. *cp = tolower(*cp);
  109. return string;
  110. }
  111. static const char *
  112. password_check(const char *old, const char *newval, const struct passwd *pwdp)
  113. {
  114. const char *msg;
  115. char *newmono, *wrapped;
  116. int lenwrap;
  117. if (strcmp(newval, old) == 0)
  118. return "no change";
  119. if (simple(newval))
  120. return "too simple";
  121. msg = NULL;
  122. newmono = str_lower(bb_xstrdup(newval));
  123. lenwrap = strlen(old);
  124. wrapped = (char *) xmalloc(lenwrap * 2 + 1);
  125. str_lower(strcpy(wrapped, old));
  126. if (palindrome(newmono))
  127. msg = "a palindrome";
  128. else if (strcmp(wrapped, newmono) == 0)
  129. msg = "case changes only";
  130. else if (similiar(wrapped, newmono))
  131. msg = "too similiar";
  132. else {
  133. safe_strncpy(wrapped + lenwrap, wrapped, lenwrap + 1);
  134. if (strstr(wrapped, newmono))
  135. msg = "rotated";
  136. }
  137. bzero(newmono, strlen(newmono));
  138. bzero(wrapped, lenwrap * 2);
  139. free(newmono);
  140. free(wrapped);
  141. return msg;
  142. }
  143. static const char *
  144. obscure_msg(const char *old, const char *newval, const struct passwd *pwdp)
  145. {
  146. int maxlen, oldlen, newlen;
  147. char *new1, *old1;
  148. const char *msg;
  149. oldlen = strlen(old);
  150. newlen = strlen(newval);
  151. #if 0 /* why not check the password when set for the first time? --marekm */
  152. if (old[0] == '\0')
  153. /* return (1); */
  154. return NULL;
  155. #endif
  156. if (newlen < 5)
  157. return "too short";
  158. /*
  159. * Remaining checks are optional.
  160. */
  161. /* Not for us -- Sean
  162. *if (!getdef_bool("OBSCURE_CHECKS_ENAB"))
  163. * return NULL;
  164. */
  165. msg = password_check(old, newval, pwdp);
  166. if (msg)
  167. return msg;
  168. /* The traditional crypt() truncates passwords to 8 chars. It is
  169. possible to circumvent the above checks by choosing an easy
  170. 8-char password and adding some random characters to it...
  171. Example: "password$%^&*123". So check it again, this time
  172. truncated to the maximum length. Idea from npasswd. --marekm */
  173. maxlen = 8;
  174. if (oldlen <= maxlen && newlen <= maxlen)
  175. return NULL;
  176. new1 = (char *) bb_xstrdup(newval);
  177. old1 = (char *) bb_xstrdup(old);
  178. if (newlen > maxlen)
  179. new1[maxlen] = '\0';
  180. if (oldlen > maxlen)
  181. old1[maxlen] = '\0';
  182. msg = password_check(old1, new1, pwdp);
  183. bzero(new1, newlen);
  184. bzero(old1, oldlen);
  185. free(new1);
  186. free(old1);
  187. return msg;
  188. }
  189. /*
  190. * Obscure - see if password is obscure enough.
  191. *
  192. * The programmer is encouraged to add as much complexity to this
  193. * routine as desired. Included are some of my favorite ways to
  194. * check passwords.
  195. */
  196. extern int obscure(const char *old, const char *newval, const struct passwd *pwdp)
  197. {
  198. const char *msg = obscure_msg(old, newval, pwdp);
  199. /* if (msg) { */
  200. if (msg != NULL) {
  201. printf("Bad password: %s.\n", msg);
  202. /* return 0; */
  203. return 1;
  204. }
  205. /* return 1; */
  206. return 0;
  207. }