diff --git a/pool/base.php b/pool/base.php index 860de7c6..aab770b9 100644 --- a/pool/base.php +++ b/pool/base.php @@ -65,6 +65,12 @@ function emailStr($str) return preg_replace(array($all,$beg,$fin), '', $str); } # +function passrequires() +{ + return "Passwords require 6 or more characters, including
" . + "at least one of each uppercase, lowercase and a digit, but not Tab"; +} +# function safepass($pass) { if (strlen($pass) < 6) @@ -171,7 +177,17 @@ function dbd($data, $user) # function dbdown() { - gopage(NULL, 'dbd', 'dbd', NULL, '', '', true, false, false); + gopage(NULL, 'dbd', 'dbd', def_menu(), '', '', true, false, false); +} +# +function syse($data, $user) +{ + return "
System error
"; +} +# +function syserror() +{ + gopage(NULL, 'syse', 'syse', def_menu(), '', '', true, false, false); } # function f404($data) @@ -181,7 +197,7 @@ function f404($data) # function do404() { - gopage(NULL, 'f404', 'f404', NULL, '', '', true, false, false); + gopage(NULL, 'f404', 'f404', def_menu(), '', '', true, false, false); } # function showPage($page, $menu, $name, $user) @@ -200,7 +216,7 @@ function showPage($page, $menu, $name, $user) # function showIndex() { - showPage('index', NULL, '', false); + showPage('index', def_menu(), '', false); } # function offline() @@ -250,7 +266,8 @@ function logout() function requestRegister() { $reg = getparam('Register', false); - if ($reg !== NULL) + $reg2 = getparam('Reset', false); + if ($reg !== NULL || $reg2 !== NULL) { logout(); return true; diff --git a/pool/db.php b/pool/db.php index ab67c284..9bff93f2 100644 --- a/pool/db.php +++ b/pool/db.php @@ -65,6 +65,12 @@ function repDecode($rep) return $ans; } # +# Convenience function +function zeip() +{ + return $_SERVER['REMOTE_ADDR']; +} +# function msgEncode($cmd, $id, $fields, $user) { global $send_sep, $fld_sep, $val_sep; @@ -75,7 +81,7 @@ function msgEncode($cmd, $id, $fields, $user) $msg .= $name . $val_sep . $value . $fld_sep; $msg .= 'createcode' . $val_sep . 'php' . $fld_sep; $msg .= 'createby' . $val_sep . $user . $fld_sep; - $msg .= 'createinet' . $val_sep . $_SERVER['REMOTE_ADDR']; + $msg .= 'createinet' . $val_sep . zeip(); return $msg; } # @@ -112,7 +118,7 @@ function checkPass($user, $pass) { $passhash = myhash($pass); $flds = array('username' => $user, 'passwordhash' => $passhash); - $msg = msgEncode('chkpass', 'log', $flds, $user); + $msg = msgEncode('chkpass', 'chkpass', $flds, $user); $rep = sendsockreply('checkPass', $msg); if (!$rep) dbdown(); @@ -124,13 +130,24 @@ function setPass($user, $oldpass, $newpass) $oldhash = myhash($oldpass); $newhash = myhash($newpass); $flds = array('username' => $user, 'oldhash' => $oldhash, 'newhash' => $newhash); - $msg = msgEncode('newpass', 'log', $flds, $user); + $msg = msgEncode('newpass', 'newpass', $flds, $user); $rep = sendsockreply('setPass', $msg); if (!$rep) dbdown(); return repDecode($rep); } # +function resetPass($user, $newpass) +{ + $newhash = myhash($newpass); + $flds = array('username' => $user, 'newhash' => $newhash); + $msg = msgEncode('newpass', 'newpass', $flds, $user); + $rep = sendsockreply('resetPass', $msg); + if (!$rep) + dbdown(); + return repDecode($rep); +} +# function userReg($user, $email, $pass) { $passhash = myhash($pass); @@ -204,4 +221,78 @@ function getBlocks($user) return repDecode($rep); } # +# e.g. $atts = array('ua_Reset.str' => 'FortyTwo', +# 'ua_Reset.date' => 'now+3600') +# 'ua_Tanuki.str' => 'Meme', +# 'ua_Tanuki.date' => 'now'); +function setAtts($user, $atts) +{ + if ($user == false) + showIndex(); + $flds = array_merge(array('username' => $user), $atts); + $msg = msgEncode('setatts', 'setatts', $flds, $user); + $rep = sendsockreply('setAtts', $msg); + if (!$rep) + dbdown(); + return repDecode($rep); +} +# +# e.g. $attlist = 'Reset.str,Reset.dateexp,Tanuki.str,Tanuki.date' +function getAtts($user, $attlist) +{ + if ($user == false) + showIndex(); + $flds = array('username' => $user, 'attlist' => $attlist); + $msg = msgEncode('getatts', 'getatts', $flds, $user); + $rep = sendsockreply('getAtts', $msg); + if (!$rep) + dbdown(); + return repDecode($rep); +} +# +# e.g. $attlist = 'Reset,Tanuki' +# effectively makes the useratts disappear (i.e. expired) +function expAtts($user, $attlist) +{ + if ($user == false) + showIndex(); + $flds = array('username' => $user, 'attlist' => $attlist); + $msg = msgEncode('expatts', 'expatts', $flds, $user); + $rep = sendsockreply('expAtts', $msg); + if (!$rep) + dbdown(); + return repDecode($rep); +} +# +# e.g. $opts = array('oc_BlockAmountHalf.value' => '25', +# 'oc_BlockAmountHalf.height' => '210000', +# 'oc_BlockAmountHalf.date' => '2012-11-28 15:25:01+00', +# 'oc_BlockAmountQuarter.value' => '12.5', +# 'oc_BlockAmountQuarter.height' => '420000'); +# *.value is always required +function setOpts($user, $opts) +{ + if ($user == false) + showIndex(); + $flds = array_merge(array('username' => $user), $opts); + $msg = msgEncode('setopts', 'setopts', $flds, $user); + $rep = sendsockreply('setOpts', $msg); + if (!$rep) + dbdown(); + return repDecode($rep); +} +# +# e.g. $optlist = 'KWebURL,BlockAmountQuarter' +function getOpts($user, $optlist) +{ + if ($user == false) + showIndex(); + $flds = array('username' => $user, 'optlist' => $optlist); + $msg = msgEncode('getopts', 'getopts', $flds, $user); + $rep = sendsockreply('getOpts', $msg); + if (!$rep) + dbdown(); + return repDecode($rep); +} +# ?> diff --git a/pool/email.php b/pool/email.php new file mode 100644 index 00000000..dbc5a506 --- /dev/null +++ b/pool/email.php @@ -0,0 +1,116 @@ + diff --git a/pool/page.php b/pool/page.php index d042864a..ed8945bb 100644 --- a/pool/page.php +++ b/pool/page.php @@ -327,8 +327,7 @@ function pgtop($dotop, $user, $douser) -
 
   -
+   "; } else @@ -355,10 +354,6 @@ function pgtop($dotop, $user, $douser) # function pgmenu($menus) { - if ($menus == NULL) - $menus = array('Home'=>array('Home'=>'')); -// $menus = array('Home'=>array('Home'=>''),'gap'=>NULL,'Help'=>array('Help'=>'help')); - $ret = "\n"; $ret .= '
'; $ret .= ''; diff --git a/pool/page_reg.php b/pool/page_reg.php index edc86fee..43326c7a 100644 --- a/pool/page_reg.php +++ b/pool/page_reg.php @@ -1,8 +1,9 @@ Register'; + $pg = '

- + + +
'; + + $pg .= '

Register

'; if (isset($data['error'])) $pg .= "
".$data['error']." - please try again

"; $pg .= makeForm(''); @@ -30,10 +33,33 @@ function doreg($data, $u)
 

All fields are required

* + All fields are required

". passrequires() . "
+"; + + $pg.= '
'; + + $pg .= '

Password Reset

'; + $pg .= makeForm(''); + $pg .= " + + + + + + + + +
Username:
Email:
 

* + All fields are required

+An Email will be sent to you, to let you reset your password
"; + $pg .= '
'; + return $pg; } # @@ -53,7 +79,7 @@ function doreg2($data) return $pg; } # -function show_reg($page, $menu, $name, $u) +function try_reg($page, $menu, $name, $u) { $user = getparam('user', false); $mail = trim(getparam('mail', false)); @@ -80,8 +106,7 @@ function show_reg($page, $menu, $name, $u) if (safepass($pass) !== true) { $ok = false; - $data['error'] = "Password is unsafe - requires 6 or more characters, including
" . - "at least one of each uppercase, lowercase and digits, but not Tab"; + $data['error'] = "Password is unsafe"; } elseif ($pass2 != $pass) { @@ -108,7 +133,86 @@ function show_reg($page, $menu, $name, $u) $data['error'] = "Invalid username, password or email address"; } - gopage($data, 'doreg', $page, $menu, $name, $u, true, true, false); + gopage($data, 'doregres', $page, $menu, $name, $u, true, true, false); +} +# +function doreset2($data) +{ + $user = $data['user']; + $email = $data['email']; + + $emailinfo = getOpts($user, emailOptList()); + if ($emailinfo['STATUS'] != 'ok') + syserror(); + + $ans = getAtts($user, 'KLastReset.dateexp'); + if ($ans['STATUS'] != 'ok') + syserror(); + + // If the last attempt hasn't expired don't do anything but show a fake msg + if (!isset($ans['KLastReset.dateexp']) || $ans['KLastReset.dateexp'] == 'Y') + { + // This line $code = isn't an attempt at security - + // it's simply to ensure the username is readable when we get it back + $code = bin2hex($data['user']). '_'; + + // A code that's large enough to not be worth guessing + $ran = $ans['STAMP'].$user.$email.rand(100000000,999999999); + $hash = hash('md4', $ran); + + $ans = setAtts($user, array('ua_KReset.str' => $hash, + 'ua_KReset.date' => 'now+3600', + 'ua_LastReset.date' => 'now+3600')); + if ($ans['STATUS'] != 'ok') + syserror(); + + $ok = passReset($email, $code.$hash, zeip(), $emailinfo); + if ($ok === false) + syserror(); + } + + $pg = '

Reset Sent

'; + $pg .= '
An Email has been sent that will allow you to'; + $pg .= '
reset your password.'; + $pg .= '
If you got your username or email address wrong,'; + $pg .= '
you wont get the email.'; + return $pg; +} +# +function try_reset($page, $menu, $name, $u) +{ + $user = getparam('user', false); + $mail = trim(getparam('mail', false)); + + // Slow this right down + usleep(500000); + + $data = array(); + + if (!nuem($user)) + $user = loginStr($user); + + if (!nuem($user) && !nuem($mail)) + { + $ans = userSettings($user); + if ($ans['STATUS'] == 'ok' && isset($ans['email']) && $ans['email'] == $mail) + { + $data = array('user' => $user, 'email' => $mail); + + gopage($data, 'doreset2', $page, $menu, $name, $u, true, true, false); + } + } + + gopage($data, 'doregres', $page, $menu, $name, $u, true, true, false); +} +# +function show_reg($page, $menu, $name, $u) +{ + $reg = getparam('Register', false); + if ($reg !== NULL) + try_reg($page, $menu, $name, $u); + else + try_reset($page, $menu, $name, $u); } # ?> diff --git a/pool/page_reset.php b/pool/page_reset.php new file mode 100644 index 00000000..7dc584fe --- /dev/null +++ b/pool/page_reset.php @@ -0,0 +1,166 @@ +
'; + + $pg .= '

Password Reset

'; + if ($error !== null) + $pg .= "
$error - please try again

"; + $pg .= makeForm('reset'); + $pg .= " + + + + + + + + + +
Enter a new password twice.
+" . passrequires() . " +
Password:
Retype Password:
 

* + All fields are required
+"; + + $pg .= '
'; + + return $pg; +} +# +function yok() +{ + $pg = '

Password Reset

'; + $pg .= '
Your password has been reset,'; + $pg .= '
login with it on the Home page.'; + return $pg; +} +# +function resetfail() +{ + if (isset($_SESSION['reset_user'])) + unset($_SESSION['reset_user']); + if (isset($_SESSION['reset_hash'])) + unset($_SESSION['reset_hash']); + if (isset($_SESSION['reset_email'])) + unset($_SESSION['reset_email']); + $pg = '

Reset Failed

'; + $pg .= '
Try again from the Home page Register/Reset button later'; + return $pg; +} +# +function dbreset() +{ + $user = $_SESSION['reset_user']; + $hash = $_SESSION['reset_hash']; + $email = $_SESSION['reset_email']; + + $pass = getparam('pass', true); + $pass2 = getparam('pass2', true); + + if (nuem($pass) || nuem($pass2)) + return allow_reset('Enter both passwords'); + + if ($pass2 != $pass) + return allow_reset("Passwords don't match"); + + if (safepass($pass) !== true) + return allow_reset('Password is unsafe'); + + $ans = getAtts($user, 'KReset.str,KReset.dateexp'); + if ($ans['STATUS'] != 'ok') + return resetfail(); + + if (!isset($ans['KReset.dateexp']) || $ans['KReset.dateexp'] == 'Y') + return resetfail(); + + if (!isset($ans['KReset.str']) || $ans['KReset.str'] != $hash) + return resetfail(); + + $emailinfo = getOpts($user, emailOptList()); + if ($emailinfo['STATUS'] != 'ok') + syserror(); + + $ans = resetPass($user, $pass); + if ($ans['STATUS'] != 'ok') + syserror(); + + unset($_SESSION['reset_user']); + unset($_SESSION['reset_hash']); + unset($_SESSION['reset_email']); + + $ans = expAtts($user, 'KReset'); + + $ok = passWasReset($email, zeip(), $emailinfo); + + return yok(); +} +# +function doreset($data, $u) +{ + // Slow this right down + usleep(500000); + + if (isset($_SESSION['reset_user']) + && isset($_SESSION['reset_hash']) + && isset($_SESSION['reset_email'])) + return dbreset(); + + $code = getparam('code', true); + if (nuem($code)) + return resetfail(); + + $codes = explode('_', $code, 2); + + if (sizeof($codes) != 2) + return resetfail(); + + $userhex = $codes[0]; + + if (strlen($userhex) == 0 || strlen($userhex) % 2) + return resetfail(); + + $user = loginStr(pack("H*" , $userhex)); + + $hash = preg_replace('/[^A-Fa-f0-9]/', '', $codes[1]); + + if (!nuem($user) && !nuem($hash)) + { + $ans = getAtts($user, 'KReset.str,KReset.dateexp'); + if ($ans['STATUS'] != 'ok') + return resetfail(); + + if (!isset($ans['KReset.dateexp']) || $ans['KReset.dateexp'] == 'Y') + return resetfail(); + + if (!isset($ans['KReset.str']) || $ans['KReset.str'] != $hash) + return resetfail(); + + $ans = userSettings($user); + if ($ans['STATUS'] != 'ok') + return resetfail(); + + if (!isset($ans['email'])) + return resetfail(); + + $email = $ans['email']; + + $_SESSION['reset_user'] = $user; + $_SESSION['reset_hash'] = $hash; + $_SESSION['reset_email'] = $email; + + return allow_reset(null); + } + return resetfail(); +} +# +function show_reset($page, $menu, $name, $u) +{ + gopage(array(), 'doreset', $page, $menu, $name, $u, true, true, false); +} +# +?> diff --git a/pool/prime.php b/pool/prime.php index 55fba0b0..d6599b7d 100644 --- a/pool/prime.php +++ b/pool/prime.php @@ -6,28 +6,8 @@ $stt = microtime(); include_once('param.php'); include_once('base.php'); # -function process($p, $user) +function process($p, $user, $menu) { - $menu = array( - 'Home' => array( - 'Home' => '' - ), - 'Account' => array( - 'Workers' => 'workers', - 'Payments' => 'payments', - 'Settings' => 'settings' - ), - 'Pool' => array( - 'Stats' => 'stats', - 'Blocks' => 'blocks' - ), - 'Admin' => NULL, - 'gap' => NULL, - 'Help' => array( - 'Help' => 'help', - 'Payouts' => 'payout' - ) - ); if ($user == 'Kano' || $user == 'ckolivas' || $user == 'wvr2' || $user == 'aphorise') { $menu['Admin']['ckp'] = 'ckp'; @@ -35,7 +15,10 @@ function process($p, $user) $menu['Admin']['AllWork'] = 'allwork'; } else - unset($menu['Admin']); + { + if (isset($menu['Admin'])) + unset($menu['Admin']); + } $page = ''; $n = ''; foreach ($menu as $item => $options) @@ -53,21 +36,60 @@ function process($p, $user) showPage($page, $menu, $n, $user); } # +function def_menu() +{ + $dmenu = array('Home' => array('Home' => ''), + 'gap' => NULL, + 'Help' => array('Help' => 'help', + 'Payouts' => 'payout')); + return $dmenu; +} +# function check() { + $dmenu = def_menu(); + $menu = array( + 'Home' => array( + 'Home' => '' + ), + 'Account' => array( + 'Workers' => 'workers', + 'Payments' => 'payments', + 'Settings' => 'settings' + ), + 'Pool' => array( + 'Stats' => 'stats', + 'Blocks' => 'blocks' + ), + 'Admin' => NULL, + 'gap' => NULL, + 'Help' => array( + 'Help' => 'help', + 'Payouts' => 'payout' + ) + ); tryLogInOut(); $who = loggedIn(); if ($who === false) { - if (requestRegister() == true) - showPage('reg', NULL, '', $who); + $p = getparam('k', true); + if ($p == 'reset') + showPage('reset', $dmenu, '', $who); else - showIndex(); + { + if (requestRegister() == true) + showPage('reg', $dmenu, '', $who); + else + { + $p = getparam('k', true); + process($p, $who, $dmenu); + } + } } else { $p = getparam('k', true); - process($p, $who); + process($p, $who, $menu); } } # diff --git a/sql/ckdb.sql b/sql/ckdb.sql index 9292f27c..7285972c 100644 --- a/sql/ckdb.sql +++ b/sql/ckdb.sql @@ -415,4 +415,4 @@ CREATE TABLE version ( PRIMARY KEY (vlock) ); -insert into version (vlock,version) values (1,'0.9'); +insert into version (vlock,version) values (1,'0.9.2'); diff --git a/sql/initid.sh b/sql/initid.sh index c2699ecb..31c119d9 100755 --- a/sql/initid.sh +++ b/sql/initid.sh @@ -2,25 +2,10 @@ # fldsep="`echo -e '\x09'`" # -dsp() -{ - cut -c4- -# echo -} -process() -{ - # <256 - len=${#1} - oct="`printf '%03o' "$len"`" - code="`printf "\\\\$oct"`" - all="$code$zero$zero$zero$1" - printf "$code\\0\\0\\000$1" | nc -U -w 1 /opt/ckdb/listener | dsp -} -# addid() { msg="newid.$1.idname=$1${fldsep}idvalue=$2" - process "$msg" + echo "$msg" } # # Default to yyyymmddXXXXXX diff --git a/src/ckdb.c b/src/ckdb.c index c8bfd20d..b6aae128 100644 --- a/src/ckdb.c +++ b/src/ckdb.c @@ -49,7 +49,7 @@ #define DB_VLOCK "1" #define DB_VERSION "0.9.2" -#define CKDB_VERSION DB_VERSION"-0.313" +#define CKDB_VERSION DB_VERSION"-0.320" #define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL_HERE __FILE__, __func__, __LINE__ @@ -2710,7 +2710,7 @@ static K_ITEM *find_userid(int64_t userid) return find_in_ktree(userid_root, &look, cmp_userid, ctx); } -// TODO: endian? +// TODO: endian? (to avoid being all zeros?) static void make_salt(USERS *users) { long int r1, r2, r3, r4; @@ -2976,13 +2976,14 @@ static K_ITEM *users_add(PGconn *conn, char *username, char *emailaddress, STRNCPY(row->username, username); row->status[0] = '\0'; STRNCPY(row->emailaddress, emailaddress); - STRNCPY(row->passwordhash, passwordhash); snprintf(tohash, sizeof(tohash), "%s&#%s", username, emailaddress); HASH_BER(tohash, strlen(tohash), 1, hash, tmp); __bin2hex(row->secondaryuserid, (void *)(&hash), sizeof(hash)); make_salt(row); + password_hash(row->username, passwordhash, row->salt, + row->passwordhash, sizeof(row->passwordhash)); HISTORYDATEINIT(row, cd, by, code, inet); HISTORYDATETRANSFER(trf_root, row);