summaryrefslogtreecommitdiff
path: root/LedgerSMB/Session/DB.pm
blob: 1f215b13e670a323a8c5fa0d35ca56fb6581d5e4 (plain)
  1. #=====================================================================
  2. # LedgerSMB
  3. # Small Medium Business Accounting software
  4. # http://www.ledgersmb.org/
  5. #
  6. #
  7. # Copyright (C) 2006
  8. # This work contains copyrighted information from a number of sources all used
  9. # with permission. It is released under the GNU General Public License
  10. # Version 2 or, at your option, any later version. See COPYRIGHT file for
  11. # details.
  12. #
  13. #
  14. #======================================================================
  15. #
  16. # This file has undergone whitespace cleanup.
  17. #
  18. #======================================================================
  19. # This package contains session related functions:
  20. #
  21. # check - checks validity of session based on the user's cookie and login
  22. #
  23. # create - creates a new session, writes cookie upon success
  24. #
  25. # destroy - destroys session
  26. #====================================================================
  27. package Session;
  28. sub session_check {
  29. my ($cookie, $form) = @_;
  30. my ($sessionid, $token) = split /:/, $cookie;
  31. # use the central database handle
  32. my $dbh = ${LedgerSMB::Sysconfig::GLOBALDBH};
  33. my $checkQuery = $dbh->prepare("SELECT sl_login FROM session WHERE session_id = ? AND token = ? AND last_used > now() - ?::interval");
  34. my $updateAge = $dbh->prepare("UPDATE session SET last_used = now() WHERE session_id = ?;");
  35. #must be an integer
  36. $sessionid =~ s/[^0-9]//g;
  37. $sessionid = int $sessionid;
  38. #must be 32 chars long and contain hex chars
  39. $token =~ s/[^0-9a-f]//g;
  40. $token = substr($token, 0, 32);
  41. if (!$myconfig{timeout}){
  42. $timeout = "1 day";
  43. } else {
  44. $timeout = "$myconfig{timeout} seconds";
  45. }
  46. $checkQuery->execute($sessionid, $token, $timeout)
  47. || $form->dberror(__FILE__.':'.__LINE__.': Looking for session: ');
  48. my $sessionValid = $checkQuery->rows;
  49. if($sessionValid){
  50. #user has a valid session cookie, now check the user
  51. my ($sessionLogin) = $checkQuery->fetchrow_array;
  52. my $login = $form->{login};
  53. $login =~ s/[^a-zA-Z0-9@.-]//g;
  54. if($sessionLogin eq $login){
  55. $updateAge->execute($sessionid) || $form->dberror(__FILE__.':'.__LINE__.': Updating session age: ');
  56. return 1;
  57. } else {
  58. #something's wrong, they have the cookie, but wrong user. Hijack attempt?
  59. #delete the cookie in the browser
  60. print qq|Set-Cookie: LedgerSMB=; path=/;\n|;
  61. return 0;
  62. }
  63. } else {
  64. #cookie is not valid
  65. #delete the cookie in the browser
  66. print qq|Set-Cookie: LedgerSMB=; path=/;\n|;
  67. print qq|Set-Cookie: DiedHere=true; path=/;\n|;
  68. return 0;
  69. }
  70. }
  71. sub session_create {
  72. my ($form) = @_;
  73. # use the central database handle
  74. my $dbh = ${LedgerSMB::Sysconfig::GLOBALDBH};
  75. # TODO Change this to use %myconfig
  76. my $deleteExisting = $dbh->prepare("DELETE FROM session WHERE sl_login = ? AND age(last_used) > ?::interval");
  77. my $seedRandom = $dbh->prepare("SELECT setseed(?);");
  78. my $fetchSequence = $dbh->prepare("SELECT nextval('session_session_id_seq'), md5(random());");
  79. my $createNew = $dbh->prepare("INSERT INTO session (session_id, sl_login, token) VALUES(?, ?, ?);");
  80. # this is assuming that $form->{login} is safe, which might be a bad assumption
  81. # so, I'm going to remove some chars, which might make previously valid logins invalid
  82. my $login = $form->{login};
  83. $login =~ s/[^a-zA-Z0-9@.-]//g;
  84. #delete any existing stale sessions with this login if they exist
  85. if (!$myconfig{timeout}){
  86. $myconfig{timeout} = 86400;
  87. }
  88. $deleteExisting->execute($login, "$myconfig{timeout} seconds") || $form->dberror(__FILE__.':'.__LINE__.': Delete from session: ');
  89. #doing the md5 and random stuff in the db so that LedgerSMB won't
  90. #require new perl modules (Digest::MD5 and a good random generator)
  91. $fetchSequence->execute() || $form->dberror(__FILE__.':'.__LINE__.': Fetch sequence id: ');
  92. my ($newSessionID, $newToken) = $fetchSequence->fetchrow_array;
  93. #create a new session
  94. $createNew->execute($newSessionID, $login, $newToken) || $form->dberror(__FILE__.':'.__LINE__.': Create new session: ');
  95. #reseed the random number generator
  96. my $randomSeed = 1.0 * ('0.'. (time() ^ ($$ + ($$ <<15))));
  97. $seedRandom->execute($randomSeed)|| $form->dberror(__FILE__.':'.__LINE__.': Reseed random generator: ');
  98. $newCookieValue = $newSessionID . ':' . $newToken;
  99. #now set the cookie in the browser
  100. #TODO set domain from ENV, also set path to install path
  101. print qq|Set-Cookie: LedgerSMB=$newCookieValue; path=/;\n|;
  102. $form->{LedgerSMB} = $newCookieValue;
  103. }
  104. sub session_destroy {
  105. # Under the current architecture, this function is a bit problematic
  106. # %myconfig is often not defined when this function needs to be called.
  107. # which means that the db connection parameters are not available.
  108. # moving user prefs and the session table into a central db will solve this issue
  109. my ($form) = @_;
  110. my $login = $form->{login};
  111. $login =~ s/[^a-zA-Z0-9@.-]//g;
  112. # use the central database handle
  113. my $dbh = ${LedgerSMB::Sysconfig::GLOBALDBH};
  114. my $deleteExisting = $dbh->prepare("DELETE FROM session WHERE sl_login = ?;");
  115. $deleteExisting->execute($login) || $form->dberror(__FILE__.':'.__LINE__.': Delete from session: ');
  116. #delete the cookie in the browser
  117. print qq|Set-Cookie: LedgerSMB=; path=/;\n|;
  118. }
  119. 1;