diff options
author | Andrew Dolgov <[email protected]> | 2013-04-13 18:24:27 +0400 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2013-04-13 18:24:41 +0400 |
commit | 044cff2d74ece46256201695346d1a0d1d66c746 (patch) | |
tree | f8c4c039e69bde071b74ca27f35839f0a3a55eb7 | |
parent | 5b27cb05a8af1bcf741a3885b17fc7d03d456c5f (diff) |
implement basic feed authentication parameter encryption in the database (FEED_CRYPT_KEY)
-rw-r--r-- | classes/pref/feeds.php | 36 | ||||
-rw-r--r-- | config.php-dist | 7 | ||||
-rw-r--r-- | include/crypt.php | 36 | ||||
-rw-r--r-- | include/functions.php | 12 | ||||
-rw-r--r-- | include/rssfuncs.php | 9 | ||||
-rw-r--r-- | include/sanity_check.php | 8 | ||||
-rw-r--r-- | include/sanity_config.php | 4 | ||||
-rw-r--r-- | install/index.php | 27 |
8 files changed, 130 insertions, 9 deletions
diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php index f57cc37d6..4a77ed8cf 100644 --- a/classes/pref/feeds.php +++ b/classes/pref/feeds.php @@ -528,6 +528,9 @@ class Pref_Feeds extends Handler_Protected { "SELECT * FROM ttrss_feeds WHERE id = '$feed_id' AND owner_uid = " . $_SESSION["uid"]); + $auth_pass_encrypted = sql_bool_to_bool(db_fetch_result($result, 0, + "auth_pass_encrypted")); + $title = htmlspecialchars(db_fetch_result($result, 0, "title")); @@ -613,7 +616,14 @@ class Pref_Feeds extends Handler_Protected { placeHolder=\"".__("Login")."\" name=\"auth_login\" value=\"$auth_login\"><hr/>"; - $auth_pass = htmlspecialchars(db_fetch_result($result, 0, "auth_pass")); + $auth_pass = db_fetch_result($result, 0, "auth_pass"); + + if ($auth_pass_encrypted) { + require_once "crypt.php"; + $auth_pass = decrypt_string($auth_pass); + } + + $auth_pass = htmlspecialchars($auth_pass); print "<input dojoType=\"dijit.form.TextBox\" type=\"password\" name=\"auth_pass\" placeHolder=\"".__("Password")."\" @@ -936,6 +946,14 @@ class Pref_Feeds extends Handler_Protected { $mark_unread_on_update = checkbox_to_sql_bool( db_escape_string($this->link, $_POST["mark_unread_on_update"])); + if (strlen(FEED_CRYPT_KEY) > 0) { + require_once "crypt.php"; + $auth_pass = substr(encrypt_string($auth_pass), 0, 250); + $auth_pass_encrypted = 'true'; + } else { + $auth_pass_encrypted = 'false'; + } + if (get_pref($this->link, 'ENABLE_FEED_CATS')) { if ($cat_id && $cat_id != 0) { $category_qpart = "cat_id = '$cat_id',"; @@ -958,6 +976,7 @@ class Pref_Feeds extends Handler_Protected { purge_interval = '$purge_intl', auth_login = '$auth_login', auth_pass = '$auth_pass', + auth_pass_encrypted = $auth_pass_encrypted, private = $private, cache_images = $cache_images, hide_images = $hide_images, @@ -1003,7 +1022,8 @@ class Pref_Feeds extends Handler_Protected { break; case "auth_pass": - $qpart = "auth_pass = '$auth_pass'"; + $qpart = "auth_pass = '$auth_pass' AND + auth_pass_encrypted = $auth_pass_encrypted"; break; case "private": @@ -1841,12 +1861,20 @@ class Pref_Feeds extends Handler_Protected { "SELECT id FROM ttrss_feeds WHERE feed_url = '$feed' AND owner_uid = ".$_SESSION["uid"]); + if (strlen(FEED_CRYPT_KEY) > 0) { + require_once "crypt.php"; + $pass = substr(encrypt_string($pass), 0, 250); + $auth_pass_encrypted = 'true'; + } else { + $auth_pass_encrypted = 'false'; + } + if (db_num_rows($result) == 0) { $result = db_query($this->link, "INSERT INTO ttrss_feeds - (owner_uid,feed_url,title,cat_id,auth_login,auth_pass,update_method) + (owner_uid,feed_url,title,cat_id,auth_login,auth_pass,update_method,auth_pass_encrypted) VALUES ('".$_SESSION["uid"]."', '$feed', - '[Unknown]', $cat_qpart, '$login', '$pass', 0)"); + '[Unknown]', $cat_qpart, '$login', '$pass', 0, $auth_pass_encrypted)"); } db_query($this->link, "COMMIT"); diff --git a/config.php-dist b/config.php-dist index eb3339742..fc999354b 100644 --- a/config.php-dist +++ b/config.php-dist @@ -24,6 +24,13 @@ // You need to set this option correctly otherwise several features // including PUSH, bookmarklets and browser integration will not work properly. + define('FEED_CRYPT_KEY', ''); + // Key used for encryption of login/passwords for password-protected feeds + // in the database. A string of 24 random characters. If left blank, encryption + // is not used. Requires mcrypt functions. + // Warning: changing this key will make your stored feed passwords impossible + // to decrypt. + define('SINGLE_USER_MODE', false); // Operate in single user mode, disables all functionality related to // multiple users and authentication. Enabling this assumes you have diff --git a/include/crypt.php b/include/crypt.php new file mode 100644 index 000000000..f06483ef1 --- /dev/null +++ b/include/crypt.php @@ -0,0 +1,36 @@ +<?php + function decrypt_string($str) { + $pair = explode(":", $str); + + if (count($pair) == 2) { + @$iv = base64_decode($pair[0]); + @$encstr = base64_decode($pair[1]); + + if ($iv && $encstr) { + $key = hash('SHA256', FEED_CRYPT_KEY, true); + + $str = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encstr, + MCRYPT_MODE_CBC, $iv); + + if ($str) return rtrim($str); + } + } + + return false; + } + + function encrypt_string($str) { + $key = hash('SHA256', FEED_CRYPT_KEY, true); + + $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, + MCRYPT_MODE_CBC), MCRYPT_RAND); + + $encstr = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $str, + MCRYPT_MODE_CBC, $iv); + + $iv_base64 = base64_encode($iv); + $encstr_base64 = base64_encode($encstr); + + return "$iv_base64:$encstr_base64"; + } +?> diff --git a/include/functions.php b/include/functions.php index f5685b89a..73ed97d08 100644 --- a/include/functions.php +++ b/include/functions.php @@ -1614,12 +1614,20 @@ "SELECT id FROM ttrss_feeds WHERE feed_url = '$url' AND owner_uid = ".$_SESSION["uid"]); + if (strlen(FEED_CRYPT_KEY) > 0) { + require_once "crypt.php"; + $auth_pass = substr(encrypt_string($auth_pass), 0, 250); + $auth_pass_encrypted = 'true'; + } else { + $auth_pass_encrypted = 'false'; + } + if (db_num_rows($result) == 0) { $result = db_query($link, "INSERT INTO ttrss_feeds - (owner_uid,feed_url,title,cat_id, auth_login,auth_pass,update_method) + (owner_uid,feed_url,title,cat_id, auth_login,auth_pass,update_method,auth_pass_encrypted) VALUES ('".$_SESSION["uid"]."', '$url', - '[Unknown]', $cat_qpart, '$auth_login', '$auth_pass', 0)"); + '[Unknown]', $cat_qpart, '$auth_login', '$auth_pass', 0, $auth_pass_encrypted)"); $result = db_query($link, "SELECT id FROM ttrss_feeds WHERE feed_url = '$url' diff --git a/include/rssfuncs.php b/include/rssfuncs.php index 6e3ef4cf1..859c575cc 100644 --- a/include/rssfuncs.php +++ b/include/rssfuncs.php @@ -203,7 +203,7 @@ $result = db_query($link, "SELECT id,update_interval,auth_login, feed_url,auth_pass,cache_images,last_updated, mark_unread_on_update, owner_uid, - pubsub_state + pubsub_state, auth_pass_encrypted FROM ttrss_feeds WHERE id = '$feed'"); if (db_num_rows($result) == 0) { @@ -218,6 +218,8 @@ $mark_unread_on_update = sql_bool_to_bool(db_fetch_result($result, 0, "mark_unread_on_update")); $pubsub_state = db_fetch_result($result, 0, "pubsub_state"); + $auth_pass_encrypted = sql_bool_to_bool(db_fetch_result($result, + 0, "auth_pass_encrypted")); db_query($link, "UPDATE ttrss_feeds SET last_update_started = NOW() WHERE id = '$feed'"); @@ -225,6 +227,11 @@ $auth_login = db_fetch_result($result, 0, "auth_login"); $auth_pass = db_fetch_result($result, 0, "auth_pass"); + if ($auth_pass_encrypted) { + require_once "crypt.php"; + $auth_pass = decrypt_string($auth_pass); + } + $cache_images = sql_bool_to_bool(db_fetch_result($result, 0, "cache_images")); $fetch_url = db_fetch_result($result, 0, "feed_url"); diff --git a/include/sanity_check.php b/include/sanity_check.php index 69309290e..b4102d234 100644 --- a/include/sanity_check.php +++ b/include/sanity_check.php @@ -67,6 +67,14 @@ array_push($errors, "Javascript cache is not writable (chmod -R 777 ".CACHE_DIR."/js)"); } + if (strlen(FEED_CRYPT_KEY) != 24) { + array_push($errors, "FEED_CRYPT_KEY should be exactly 24 characters in length."); + } + + if (strlen(FEED_CRYPT_KEY) != 0 && !function_exists("mcrypt_decrypt")) { + array_push($errors, "FEED_CRYPT_KEY requires mcrypt functions which are not found."); + } + if (GENERATED_CONFIG_CHECK != EXPECTED_CONFIG_VERSION) { array_push($errors, "Configuration option checker sanity_config.php is outdated, please recreate it using ./utils/regen_config_checks.sh"); diff --git a/include/sanity_config.php b/include/sanity_config.php index cb1c1e8ca..0c829981e 100644 --- a/include/sanity_config.php +++ b/include/sanity_config.php @@ -1,3 +1,3 @@ -<?php # This file has been generated at: Mon Apr 1 18:30:54 IDT 2013 +<?php # This file has been generated at: Sat Apr 13 17:41:19 MSK 2013 define('GENERATED_CONFIG_CHECK', 26); -$requred_defines = array( 'DB_TYPE', 'DB_HOST', 'DB_USER', 'DB_NAME', 'DB_PASS', 'MYSQL_CHARSET', 'SELF_URL_PATH', 'SINGLE_USER_MODE', 'SIMPLE_UPDATE_MODE', 'PHP_EXECUTABLE', 'LOCK_DIRECTORY', 'CACHE_DIR', 'ICONS_DIR', 'ICONS_URL', 'AUTH_AUTO_CREATE', 'AUTH_AUTO_LOGIN', 'FORCE_ARTICLE_PURGE', 'PUBSUBHUBBUB_HUB', 'PUBSUBHUBBUB_ENABLED', 'SPHINX_ENABLED', 'SPHINX_INDEX', 'ENABLE_REGISTRATION', 'REG_NOTIFY_ADDRESS', 'REG_MAX_USERS', 'SESSION_COOKIE_LIFETIME', 'SESSION_CHECK_ADDRESS', 'SMTP_FROM_NAME', 'SMTP_FROM_ADDRESS', 'DIGEST_SUBJECT', 'SMTP_HOST', 'SMTP_PORT', 'SMTP_LOGIN', 'SMTP_PASSWORD', 'CHECK_FOR_NEW_VERSION', 'ENABLE_GZIP_OUTPUT', 'PLUGINS', 'CONFIG_VERSION'); ?> +$requred_defines = array( 'DB_TYPE', 'DB_HOST', 'DB_USER', 'DB_NAME', 'DB_PASS', 'MYSQL_CHARSET', 'SELF_URL_PATH', 'FEED_CRYPT_KEY', 'SINGLE_USER_MODE', 'SIMPLE_UPDATE_MODE', 'PHP_EXECUTABLE', 'LOCK_DIRECTORY', 'CACHE_DIR', 'ICONS_DIR', 'ICONS_URL', 'AUTH_AUTO_CREATE', 'AUTH_AUTO_LOGIN', 'FORCE_ARTICLE_PURGE', 'PUBSUBHUBBUB_HUB', 'PUBSUBHUBBUB_ENABLED', 'SPHINX_ENABLED', 'SPHINX_INDEX', 'ENABLE_REGISTRATION', 'REG_NOTIFY_ADDRESS', 'REG_MAX_USERS', 'SESSION_COOKIE_LIFETIME', 'SESSION_CHECK_ADDRESS', 'SMTP_FROM_NAME', 'SMTP_FROM_ADDRESS', 'DIGEST_SUBJECT', 'SMTP_HOST', 'SMTP_PORT', 'SMTP_LOGIN', 'SMTP_PASSWORD', 'CHECK_FOR_NEW_VERSION', 'ENABLE_GZIP_OUTPUT', 'PLUGINS', 'CONFIG_VERSION'); ?> diff --git a/install/index.php b/install/index.php index 3b6a1f544..1aae5da83 100644 --- a/install/index.php +++ b/install/index.php @@ -10,6 +10,25 @@ <body> <?php + function make_password($length = 8) { + + $password = ""; + $possible = "0123456789abcdfghjkmnpqrstvwxyzABCDFGHJKMNPQRSTVWXYZ*%+^"; + + $i = 0; + + while ($i < $length) { + $char = substr($possible, mt_rand(0, strlen($possible)-1), 1); + + if (!strstr($password, $char)) { + $password .= $char; + $i++; + } + } + return $password; + } + + function sanity_check($db_type) { $errors = array(); @@ -108,6 +127,12 @@ $finished = false; + if (function_exists("mcrypt_decrypt")) { + $crypt_key = make_password(24); + } else { + $crypt_key = ""; + } + foreach ($data as $line) { if (preg_match("/define\('DB_TYPE'/", $line)) { $rv .= "\tdefine('DB_TYPE', '$DB_TYPE');\n"; @@ -123,6 +148,8 @@ $rv .= "\tdefine('DB_PORT', '$DB_PORT');\n"; } else if (preg_match("/define\('SELF_URL_PATH'/", $line)) { $rv .= "\tdefine('SELF_URL_PATH', '$SELF_URL_PATH');\n"; + } else if (preg_match("/define\('FEED_CRYPT_KEY'/", $line)) { + $rv .= "\tdefine('FEED_CRYPT_KEY', '$crypt_key');\n"; } else if (!$finished) { $rv .= "$line\n"; } |