Skip to content
This repository has been archived by the owner on Oct 6, 2021. It is now read-only.

Commit

Permalink
Fix CSRF token locking and post splitting
Browse files Browse the repository at this point in the history
  • Loading branch information
paragonie-security committed Apr 6, 2016
1 parent 7e564b6 commit 72968a9
Show file tree
Hide file tree
Showing 26 changed files with 92 additions and 47 deletions.
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/board.twig
Expand Up @@ -13,7 +13,7 @@
class="board-form pure-form pure-form-stacked"
action="/bridge/board"
method="post"
>{{ form_token("/bridge/board") }}
>{{ form_token() }}
<label for="username">{{ __("Username") }}:</label>
<input type="text" id="username" name="username" placeholder="{{ __("Enter your Username") }}" required="required" class="pure-input-1" />
<div id="username_feedback">
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_admin_settings.twig
@@ -1,4 +1,4 @@
<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
<div id="admin_settings_accordion">
<h3>{{ __("Universal Configuration Settings") }}</h3>
<div id="universal">
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_blog_comments_view.twig
Expand Up @@ -77,7 +77,7 @@
</div>

{% if can('publish') %}
<form method="post">{{ form_token(cabin_url() ~ "/blog/comments/view/" ~ comment.commentid) }}
<form method="post">{{ form_token() }}

<fieldset class="form-button-group">
<legend>Administrative Actions</legend>
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_blog_posts_edit.twig
@@ -1,5 +1,5 @@
<h3>{{ __("Edit Blog Post") }}</h3>
<form method="post">{{ form_token( cabin_url() ~ "/blog/post/edit/" ~ blogpost.postid) }}
<form method="post">{{ form_token() }}
<div class="table">

<div class="table-row">
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_blog_posts_new.twig
@@ -1,5 +1,5 @@
<h3>{{ __("New Blog Post") }}</h3>
<form method="post">{{ form_token( cabin_url() ~ "/blog/post/new") }}
<form method="post">{{ form_token() }}
<div class="table">

<div class="table-row">
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_blog_series_edit.twig
@@ -1,5 +1,5 @@
<h3 class="nomargin">{{ __("Update Series") }}</h3>
<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
<input type="hidden" name="series_id" id="series_id" value="{{ series.seriesid|e('html_attr') }}" />
<div id="blog_series_metadata" class="form-table full-width table-pad-1">
<div class="table-row">
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_blog_series_new.twig
@@ -1,5 +1,5 @@
<h3 class="nomargin">{{ __("Create New Series") }}</h3>
<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
<div id="blog_series_metadata" class="form-table full-width table-pad-1">
<div class="table-row">
<label class="table-cell table-label">
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_cabins_manage.twig
@@ -1,5 +1,5 @@
<h2 class="nomargin">{{ name|e('html') }}</h2>
<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
<div id="cabin_accordion">
<h3>{{ __("Routing Information") }}</h3>
<div id="routing">
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_crew_group_edit.twig
@@ -1,5 +1,5 @@
{% import "macros/groups.twig" as grpmac %}
<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
<div class="table table-pad-1">

<div class="table-row">
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_crew_group_new.twig
@@ -1,5 +1,5 @@
{% import "macros/groups.twig" as grpmac %}
<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
<div class="table table-pad-1">

<div class="table-row">
Expand Down
4 changes: 1 addition & 3 deletions src/Cabin/Bridge/Lens/cargo/bridge_crew_user_edit.twig
@@ -1,8 +1,6 @@
{% import "macros/groups.twig" as grpmac %}
<h2>{{ __("Edit User Account") }}</h2>
<form method="post">{{ form_token(
cabin_url() ~ "/crew/users/edit/" ~ user.userid
) }}
<form method="post">{{ form_token() }}
<div class="table full-width table-pad-1">

<div class="table-row">
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_files_delete.twig
Expand Up @@ -2,7 +2,7 @@

<pre>{{ cabin_url(cabin) ~ "files/" ~ dir|e('html') ~ file.filename|e('html') }}</pre>

<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
<button type="submit" name="submit_btn" value="Confirm Delete" class="pure-button pure-button-secondary">
{{ __("Delete this File") }}
</button>
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_files_delete_dir.twig
Expand Up @@ -8,7 +8,7 @@
{% endfor %}
</ul>

<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
<button type="submit" name="submit_btn" value="Confirm Delete" class="pure-button pure-button-secondary">
{{ __("Delete everything") }}
</button>
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_files_list_forms.twig
@@ -1,5 +1,5 @@
{% set formaction = cabin_url() ~ '/' ~ path_middle ~ '/' ~ cabin ~ '?dir=' ~ current %}
<form action="{{ formaction|e('html_attr') }}" method="post" enctype="multipart/form-data">{{ form_token(formaction) }}
<form action="{{ formaction|e('html_attr') }}" method="post" enctype="multipart/form-data">{{ form_token( get_url_path(formaction) )}}
<div id="bridge_files_new_dir_form">
<fieldset>
<legend>Create a New Directory</legend>
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_files_move.twig
@@ -1,6 +1,6 @@
<h2>{{ __("Rename File?") }}</h2>

<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
<fieldset class="form-move-fieldset">
<legend>{% if root_dir %}
{{ cabin_url(cabin) ~ "files/" ~ root_dir ~ "/" ~ dir|e('html') ~ "/" ~ file.filename|e('html') }}
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_files_move_dir.twig
@@ -1,6 +1,6 @@
<h2>{{ __("Rename Folder?") }}</h2>

<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
<fieldset class="form-move-fieldset">
<legend>{% if root_dir %}
{{ cabin_url(cabin) ~ "files/" ~ root_dir ~ "/" ~ dir|e('html') ~ "/" ~ file.filename|e('html') }}
Expand Down
Expand Up @@ -2,7 +2,7 @@
{% set can_create = can_create() %}
<h2>{{ __("Permissions") }} - {{ cabin|e('html') }}</h2>

<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}

<h3>{{ __("Contexts") }}</h3>

Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_perms_context.twig
Expand Up @@ -2,7 +2,7 @@

<h2 class="nomargin">Manage Permissions</h2>

<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
<div class="table table-pad-1">
<div class="table-row">
<div class="table-cell table-label">{#
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/bridge_preferences.twig
@@ -1,5 +1,5 @@
<h3>{{ __("My Preferences") }}</h3>
<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
{% include cargo("bridge_preferences_motif") %}

{# Gadget developers: Feel free to add to this one: #}
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/cargo/my_account.twig
@@ -1,5 +1,5 @@
<h2>My Account</h2>
<form method="post" id="my_account_form">{{ form_token(cabin_url() ~ "/my/account") }}
<form method="post" id="my_account_form">{{ form_token() }}
{% if post_response %}
<div class="post {{ post_response.status|e('html_attr') }}">{{ post_response.message }}</div>
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/login.twig
Expand Up @@ -15,7 +15,7 @@
class="login-form pure-form pure-form-stacked"
action="/bridge/login"
method="post"
>{{ form_token("/bridge/login") }}
>{{ form_token() }}
{% include cargo("form_before_login") ignore missing %}
<label for="username">{{ __("Username") }}:</label>
<input type="text" id="username" name="username" placeholder="{{ __("Enter your Username") }}" class="pure-input-1" />
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Bridge/Lens/perms/action.twig
@@ -1,7 +1,7 @@
{% extends base_template() %}

{% block main %}
<form method="post">{{ form_token(_REQUEST_URI) }}
<form method="post">{{ form_token() }}
<label>{{ __("Action Name") }}</label>:
<input type="text" name="label" value="{{ action.label|e('html_attr') }}" />
<button type="submit" class="pure-button pure-button-secondary">
Expand Down
34 changes: 29 additions & 5 deletions src/Cabin/Hull/Blueprint/Blog.php
Expand Up @@ -876,6 +876,13 @@ public function getSnippet(array $post, bool $after = false): array
if (empty($post['body'])) {
return $post;
}
if ($post['format'] === 'Rich Text') {
$post['body'] = \str_replace(
'><',
'>' . "\n" . '<',
$post['body']
);
}
$lines = \explode("\n", $post['body']);
if (count($lines) < 4 || \strlen($post['body']) < 200) {
$post['snippet'] = $post['body'];
Expand All @@ -899,19 +906,33 @@ public function getSnippet(array $post, bool $after = false): array
$cutoff = $i;
break;
}
} elseif ($post['format'] === 'HTML' || $post['format'] === 'Rich Text') {
if (\preg_match('#^<h[1-7]>#', $line[0], $m)) {
$cutoff = $i;
break;
}
}
}
if ($cutoff !== null) {
$post['snippet'] = \implode("\n", \array_slice($lines, 0, $i - 1));
$post['snippet'] = \implode(
"\n",
\array_slice($lines, 0, $i - 1)
);
if ($after) {
$post['after_fold'] = \implode("\n", \array_slice($lines, $i - 1));
$post['after_fold'] = \implode(
"\n",
\array_slice($lines, $i - 1)
);
}
return $post;
}

// Next, let's find the 37% mark for breaks

$sects = \explode("\n\n", $post['body']);
$split = ($post['format'] === 'Rich Text' || $post['format'] === 'HTML')
? "\n"
: "\n\n";
$sects = \explode($split, $post['body']);
$cut = (int) \ceil(0.37 * \count($sects));
if ($sects < 2) {
$post['snippet'] = $post['body'];
Expand All @@ -921,9 +942,12 @@ public function getSnippet(array $post, bool $after = false): array
if (\preg_match('#^\.\. #', $sects[ $cut - 1 ])) {
--$cut;
}
$post['snippet'] = \implode("\n\n", \array_slice($sects, 0, $cut - 1))."\n";
$post['snippet'] = \implode(
"\n\n",
\array_slice($sects, 0, $cut - 1)
)."\n";
if ($after) {
$post['after_fold'] = "\n".\implode("\n\n", \array_slice($sects, 0, $cut - 1));
$post['after_fold'] = "\n".\implode($split, \array_slice($sects, $cut - 1));
}
return $post;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Cabin/Hull/Lens/cargo/blog_comments_form.twig
Expand Up @@ -7,7 +7,7 @@
#}{% elseif blog_error %}{#
#}<p class="blog-comment-error">{{ __(blog_error) }}</p>{#
#}{% endif %}
<form method="post" class="comment-form">{{ form_token(_REQUEST_URI) }}
<form method="post" class="comment-form">{{ form_token() }}
<div class="form-row" id="reply-to"></div>
{% if userid() %}
<div class="form-row">
Expand Down
1 change: 1 addition & 0 deletions src/config/lens.php
Expand Up @@ -105,6 +105,7 @@
$lens->func('csp_nonce');
$lens->func('get_avatar');
$lens->func('get_languages');
$lens->func('get_url_path');
$lens->func('global_config');
$lens->func('is_admin');
$lens->func('logout_token');
Expand Down
56 changes: 39 additions & 17 deletions src/lens_functions.php
Expand Up @@ -27,6 +27,23 @@ function base_template()
return $state->base_template;
}

/**
* READ-ONLY access to the state global
*
* @param string $name
* @return array
*/
function cabin_config(string $name): array
{
$state = State::instance();
foreach ($state->cabins as $route => $cabin) {
if ($cabin['name'] === $name) {
return $cabin;
}
}
return [];
}

/**
* Get the canon URL for a given Cabin
*
Expand Down Expand Up @@ -232,6 +249,28 @@ function form_token($lockTo = '')
return $csrf->insertToken($lockTo);
}

/**
* Given a URL, only grab the path component (and, optionally, the query)
*
* @param string $url
* @param bool $includeQuery
* @return string
*/
function get_path_url(string $url, bool $includeQuery = false): string
{
$path = \parse_url($url, PHP_URL_PATH);
if ($path) {
if ($includeQuery) {
$query = \parse_url($url, PHP_URL_QUERY);
if ($query) {
return $url . '?' . $query;
}
}
return $path;
}
return '';
}

/**
* Get supported languages.
*
Expand All @@ -256,23 +295,6 @@ function get_avatar(int $authorId, string $which): string
return '';
}

/**
* READ-ONLY access to the state global
*
* @param string $name
* @return array
*/
function cabin_config(string $name): array
{
$state = State::instance();
foreach ($state->cabins as $route => $cabin) {
if ($cabin['name'] === $name) {
return $cabin;
}
}
return [];
}

/**
* READ-ONLY access to the state global
*
Expand Down

0 comments on commit 72968a9

Please sign in to comment.