9auth.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #include "stdinc.h"
  2. #include "9.h"
  3. int
  4. authRead(Fid* afid, void* data, int count)
  5. {
  6. AuthInfo *ai;
  7. AuthRpc *rpc;
  8. if((rpc = afid->rpc) == nil){
  9. vtSetError("not an auth fid");
  10. return -1;
  11. }
  12. switch(auth_rpc(rpc, "read", nil, 0)){
  13. default:
  14. vtSetError("fossil authRead: auth protocol not finished");
  15. return -1;
  16. case ARdone:
  17. if((ai = auth_getinfo(rpc)) == nil){
  18. vtSetError("%r");
  19. break;
  20. }
  21. if(ai->cuid == nil || *ai->cuid == '\0'){
  22. vtSetError("auth with no cuid");
  23. auth_freeAI(ai);
  24. break;
  25. }
  26. assert(afid->cuname == nil);
  27. afid->cuname = vtStrDup(ai->cuid);
  28. auth_freeAI(ai);
  29. if(Dflag)
  30. fprint(2, "authRead cuname %s\n", afid->cuname);
  31. assert(afid->uid == nil);
  32. if((afid->uid = uidByUname(afid->cuname)) == nil){
  33. vtSetError("unknown user %#q", afid->cuname);
  34. break;
  35. }
  36. return 0;
  37. case ARok:
  38. if(count < rpc->narg){
  39. vtSetError("not enough data in auth read");
  40. break;
  41. }
  42. memmove(data, rpc->arg, rpc->narg);
  43. return rpc->narg;
  44. case ARphase:
  45. vtSetError("%r");
  46. break;
  47. }
  48. return -1;
  49. }
  50. int
  51. authWrite(Fid* afid, void* data, int count)
  52. {
  53. assert(afid->rpc != nil);
  54. if(auth_rpc(afid->rpc, "write", data, count) != ARok)
  55. return -1;
  56. return count;
  57. }
  58. int
  59. authCheck(Fcall* t, Fid* fid, Fsys* fsys)
  60. {
  61. Con *con;
  62. Fid *afid;
  63. uchar buf[1];
  64. /*
  65. * Can't lookup with FidWlock here as there may be
  66. * protocol to do. Use a separate lock to protect altering
  67. * the auth information inside afid.
  68. */
  69. con = fid->con;
  70. if(t->afid == NOFID){
  71. /*
  72. * If no authentication is asked for, allow
  73. * "none" provided the connection has already
  74. * been authenticatated.
  75. *
  76. * The console is allowed to attach without
  77. * authentication.
  78. */
  79. vtRLock(con->alock);
  80. if(con->isconsole){
  81. /* anything goes */
  82. }else if((con->flags&ConNoneAllow) || con->aok){
  83. static int noneprint;
  84. if(noneprint++ < 10)
  85. consPrint("attach %s as %s: allowing as none\n",
  86. fsysGetName(fsys), fid->uname);
  87. vtMemFree(fid->uname);
  88. fid->uname = vtStrDup(unamenone);
  89. }else{
  90. vtRUnlock(con->alock);
  91. consPrint("attach %s as %s: connection not authenticated, not console\n",
  92. fsysGetName(fsys), fid->uname);
  93. vtSetError("cannot attach as none before authentication");
  94. return 0;
  95. }
  96. vtRUnlock(con->alock);
  97. if((fid->uid = uidByUname(fid->uname)) == nil){
  98. consPrint("attach %s as %s: unknown uname\n",
  99. fsysGetName(fsys), fid->uname);
  100. vtSetError("unknown user");
  101. return 0;
  102. }
  103. return 1;
  104. }
  105. if((afid = fidGet(con, t->afid, 0)) == nil){
  106. consPrint("attach %s as %s: bad afid\n",
  107. fsysGetName(fsys), fid->uname);
  108. vtSetError("bad authentication fid");
  109. return 0;
  110. }
  111. /*
  112. * Check valid afid;
  113. * check uname and aname match.
  114. */
  115. if(!(afid->qid.type & QTAUTH)){
  116. consPrint("attach %s as %s: afid not an auth file\n",
  117. fsysGetName(fsys), fid->uname);
  118. fidPut(afid);
  119. vtSetError("bad authentication fid");
  120. return 0;
  121. }
  122. if(strcmp(afid->uname, fid->uname) != 0 || afid->fsys != fsys){
  123. consPrint("attach %s as %s: afid is for %s as %s\n",
  124. fsysGetName(fsys), fid->uname,
  125. fsysGetName(afid->fsys), afid->uname);
  126. fidPut(afid);
  127. vtSetError("attach/auth mismatch");
  128. return 0;
  129. }
  130. vtLock(afid->alock);
  131. if(afid->cuname == nil){
  132. if(authRead(afid, buf, 0) != 0 || afid->cuname == nil){
  133. vtUnlock(afid->alock);
  134. consPrint("attach %s as %s: %R\n",
  135. fsysGetName(fsys), fid->uname);
  136. fidPut(afid);
  137. vtSetError("fossil authCheck: auth protocol not finished");
  138. return 0;
  139. }
  140. }
  141. vtUnlock(afid->alock);
  142. assert(fid->uid == nil);
  143. if((fid->uid = uidByUname(afid->cuname)) == nil){
  144. consPrint("attach %s as %s: unknown cuname %s\n",
  145. fsysGetName(fsys), fid->uname, afid->cuname);
  146. fidPut(afid);
  147. vtSetError("unknown user");
  148. return 0;
  149. }
  150. vtMemFree(fid->uname);
  151. fid->uname = vtStrDup(afid->cuname);
  152. fidPut(afid);
  153. /*
  154. * Allow "none" once the connection has been authenticated.
  155. */
  156. vtLock(con->alock);
  157. con->aok = 1;
  158. vtUnlock(con->alock);
  159. return 1;
  160. }