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