passwd.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* passwd.c - Program to update user password.
  2. *
  3. * Copyright 2012 Ashwini Kumar <ak.ashwini@gmail.com>
  4. * Modified 2012 Jason Kyungwan Han <asura321@gmail.com>
  5. *
  6. * http://refspecs.linuxfoundation.org/LSB_4.1.0/LSB-Core-generic/LSB-Core-generic/passwd.html
  7. USE_PASSWD(NEWTOY(passwd, ">1a:dlu", TOYFLAG_STAYROOT|TOYFLAG_USR|TOYFLAG_BIN))
  8. config PASSWD
  9. bool "passwd"
  10. default y
  11. depends on TOYBOX_SHADOW
  12. help
  13. usage: passwd [-a ALGO] [-dlu] [USER]
  14. Update user's authentication tokens. Defaults to current user.
  15. -a ALGO Encryption method (des, md5, sha256, sha512) default: des
  16. -d Set password to ''
  17. -l Lock (disable) account
  18. -u Unlock (enable) account
  19. config PASSWD_SAD
  20. bool "Add sad password checking heuristics"
  21. default n
  22. depends on PASSWD
  23. help
  24. Password changes are checked to make sure they're at least 6 chars long,
  25. don't include the entire username (but not a subset of it), or the entire
  26. previous password (but changing password1, password2, password3 is fine).
  27. This heuristic accepts "aaaaaa" and "123456".
  28. */
  29. #define FOR_passwd
  30. #include "toys.h"
  31. GLOBALS(
  32. char *a;
  33. )
  34. // Sad advisory heuristic, won't find password1 password2 password3...
  35. static void weak_check(char *new, char *old, char *user)
  36. {
  37. char *msg = 0;
  38. if (strlen(new) < 6) msg = "too short";
  39. if (*new) {
  40. if (strcasestr(new, user) || strcasestr(user, new)) msg = "user";
  41. if (*old && (strcasestr(new, old) || strcasestr(old, new))) msg = "old";
  42. }
  43. if (msg) xprintf("BAD PASSWORD: %s\n",msg);
  44. }
  45. void passwd_main(void)
  46. {
  47. uid_t myuid;
  48. struct passwd *pw = 0;
  49. struct spwd *sp;
  50. char *pass, *name, *encrypted = 0, salt[MAX_SALT_LEN];
  51. // If we're root or not -lud, load specified user. Exit if not allowed.
  52. if (!(myuid = getuid()) || !(toys.optflags&(FLAG_l|FLAG_u|FLAG_d))) {
  53. if (*toys.optargs) pw = xgetpwnam(*toys.optargs);
  54. else pw = xgetpwuid(myuid);
  55. }
  56. if (!pw || (myuid && (myuid != pw->pw_uid))) error_exit("Not root");
  57. // Get password from /etc/passwd or /etc/shadow
  58. // TODO: why still support non-shadow passwords...?
  59. name = pw->pw_name;
  60. if (*(pass = pw->pw_passwd)=='x' && (sp = getspnam(name))) pass = sp->sp_pwdp;
  61. if (FLAG(l)) {
  62. if (*pass=='!') error_exit("already locked");
  63. printf("Locking '%s'\n", name);
  64. encrypted = xmprintf("!%s", pass);
  65. } else if (FLAG(u)) {
  66. if (*pass!='!') error_exit("already unlocked");
  67. printf("Unlocking '%s'\n", name);
  68. encrypted = pass+1;
  69. } else if (FLAG(d)) {
  70. printf("Deleting password for '%s'\n", name);
  71. *(encrypted = toybuf) = 0;
  72. } else {
  73. if (!TT.a) TT.a = "des";
  74. if (get_salt(salt, TT.a)<0) error_exit("bad -a '%s'", TT.a);
  75. printf("Changing password for %s\n", name);
  76. if (myuid) {
  77. if (*pass=='!') error_exit("'%s' locked", name);
  78. if (read_password(toybuf+2048, 2048, "Old password:")) return;
  79. pass = crypt(toybuf+2048, pw->pw_passwd);
  80. if (!pass || strcmp(pass, pw->pw_passwd)) error_exit("No");
  81. }
  82. if (read_password(toybuf, 2048, "New password:")) return;
  83. if (CFG_PASSWD_SAD) weak_check(toybuf, toybuf+2048, name);
  84. if (read_password(toybuf+2048, 2048, "Retype password:")) return;
  85. if (strcmp(toybuf, toybuf+2048)) error_exit("Passwords do not match.");
  86. encrypted = crypt(toybuf, salt);
  87. }
  88. // Update the passwd
  89. if (update_password(*pw->pw_passwd=='x' ? "/etc/shadow" : "/etc/passwd",
  90. name, encrypted, 1)) error_msg("Failure");
  91. else fprintf(stderr, "Success\n");
  92. memset(toybuf, 0, sizeof(toybuf));
  93. memset(encrypted, 0, strlen(encrypted));
  94. free(encrypted);
  95. }