password.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /* password.c */
  2. #include <u.h>
  3. #include <libc.h>
  4. #include <bio.h>
  5. #include <mp.h>
  6. #include <libsec.h>
  7. #include "SConn.h"
  8. #include "secstore.h"
  9. static Biobuf*
  10. openPW(char *id, int mode)
  11. {
  12. Biobuf *b;
  13. int nfn = strlen(SECSTORE_DIR)+strlen(id)+20;
  14. char *fn;
  15. if(validatefile(id) == nil || strcmp(id,".") == 0)
  16. return nil;
  17. fn = emalloc(nfn);
  18. snprint(fn, nfn, "%s/who/%s", SECSTORE_DIR, id);
  19. b = Bopen(fn, mode);
  20. free(fn);
  21. return b;
  22. }
  23. static ulong
  24. mtimePW(char *id)
  25. {
  26. Dir *d;
  27. int nfn = strlen(SECSTORE_DIR)+strlen(id)+20;
  28. char *fn = emalloc(nfn);
  29. ulong mt;
  30. snprint(fn, nfn, "%s/who/%s", SECSTORE_DIR, id);
  31. d = dirstat(fn);
  32. free(fn);
  33. mt = d->mtime;
  34. free(d);
  35. return mt;
  36. }
  37. PW *
  38. getPW(char *id, int dead_or_alive)
  39. {
  40. uint now = time(0);
  41. Biobuf *bin;
  42. PW *pw;
  43. char *f1, *f2; // fields 1, 2 = attribute, value
  44. if((bin = openPW(id, OREAD)) == 0){
  45. id = "FICTITIOUS";
  46. if((bin = openPW(id, OREAD)) == 0){
  47. werrstr("account does not exist");
  48. return nil;
  49. }
  50. }
  51. pw = emalloc(sizeof(*pw));
  52. pw->id = estrdup(id);
  53. pw->status |= Enabled;
  54. while( (f1 = Brdline(bin, '\n')) != 0){
  55. f1[Blinelen(bin)-1] = 0;
  56. for(f2 = f1; *f2 && (*f2!=' ') && (*f2!='\t'); f2++){}
  57. if(*f2)
  58. for(*f2++ = 0; *f2 && (*f2==' ' || *f2=='\t'); f2++){}
  59. if(strcmp(f1, "exp") == 0){
  60. pw->expire = strtoul(f2, 0, 10);
  61. }else if(strcmp(f1, "DISABLED") == 0){
  62. pw->status &= ~Enabled;
  63. }else if(strcmp(f1, "STA") == 0){
  64. pw->status |= STA;
  65. }else if(strcmp(f1, "failed") == 0){
  66. pw->failed = strtoul(f2, 0, 10);
  67. }else if(strcmp(f1, "other") == 0){
  68. pw->other = estrdup(f2);
  69. }else if(strcmp(f1, "PAK-Hi") == 0){
  70. pw->Hi = strtomp(f2, nil, 64, nil);
  71. }
  72. }
  73. Bterm(bin);
  74. if(pw->Hi == nil){
  75. werrstr("corrupted account file");
  76. freePW(pw);
  77. return nil;
  78. }
  79. if(dead_or_alive)
  80. return pw; // return PW entry for editing, whether currently valid or not
  81. if(pw->expire <= now){
  82. werrstr("account expired");
  83. freePW(pw);
  84. return nil;
  85. }
  86. if((pw->status & Enabled) == 0){
  87. werrstr("account disabled");
  88. freePW(pw);
  89. return nil;
  90. }
  91. if(pw->failed < 10)
  92. return pw; // success
  93. if(now < mtimePW(id)+300){
  94. werrstr("too many failures; try again in five minutes");
  95. freePW(pw);
  96. return nil;
  97. }
  98. pw->failed = 0;
  99. putPW(pw); // reset failed-login-counter after five minutes
  100. return pw;
  101. }
  102. int
  103. putPW(PW *pw)
  104. {
  105. Biobuf *bout;
  106. char *hexHi;
  107. if((bout = openPW(pw->id, OWRITE|OTRUNC)) ==0){
  108. werrstr("can't open PW file");
  109. return -1;
  110. }
  111. Bprint(bout, "exp %lud\n", pw->expire);
  112. if(!(pw->status & Enabled))
  113. Bprint(bout, "DISABLED\n");
  114. if(pw->status & STA)
  115. Bprint(bout, "STA\n");
  116. if(pw->failed)
  117. Bprint(bout, "failed\t%d\n", pw->failed);
  118. if(pw->other)
  119. Bprint(bout,"other\t%s\n", pw->other);
  120. hexHi = mptoa(pw->Hi, 64, nil, 0);
  121. Bprint(bout, "PAK-Hi\t%s\n", hexHi);
  122. free(hexHi);
  123. return 0;
  124. }
  125. void
  126. freePW(PW *pw)
  127. {
  128. if(pw == nil)
  129. return;
  130. free(pw->id);
  131. free(pw->other);
  132. mpfree(pw->Hi);
  133. free(pw);
  134. }