Control: tags -1 + patch
Control: found -1 5.1.4+dfsg-4
Hi Dominic,
On Tue, Dec 30, 2014 at 02:56:31AM +0100, Moritz Muehlenhoff wrote:
> Source: movabletype-opensource
> Severity: grave
> Tags: security
>
> Hi,
> please see https://movabletype.org/news/2014/12/6.0.6.html
Attaches is the extracted patch for the 5.2.x series.
Regards,
Salvatore
--- a/lib/MT/XMLRPCServer.pm 2013-11-07 04:55:39.000000000 +0100
+++ b/lib/MT/XMLRPCServer.pm 2014-12-24 11:13:10.000000000 +0100
@@ -78,6 +78,18 @@
$HAVE_XML_PARSER = $@ ? 0 : 1;
}
+sub _validate_params {
+ my ($params) = @_;
+
+ foreach my $p (@$params) {
+ die _fault( MT->translate("Invalid parameter") )
+ if ( 'ARRAY' eq ref $p )
+ or ( 'HASH' eq ref $p );
+ }
+
+ return 1;
+}
+
sub _fault {
my $mt = MT::XMLRPCServer::Util::mt_new();
my $enc = $mt->config('PublishCharset');
@@ -126,6 +138,7 @@
sub _login {
my $class = shift;
my ( $user, $pass, $blog_id ) = @_;
+
my $mt = MT::XMLRPCServer::Util::mt_new();
my $enc = $mt->config('PublishCharset');
require MT::Author;
@@ -274,11 +287,10 @@
my $cat_class = MT->model('category');
# The spec says to ignore invalid category names.
- @categories = grep {defined} $cat_class->search(
- { blog_id => $entry->blog_id,
- label => $cats,
- }
- );
+ @categories
+ = grep {defined}
+ $cat_class->search(
+ { blog_id => $entry->blog_id, label => $cats, } );
}
}
@@ -288,10 +300,7 @@
my $place;
if ($is_primary_placement) {
$place = MT::Placement->load(
- { entry_id => $entry->id,
- is_primary => 1,
- }
- );
+ { entry_id => $entry->id, is_primary => 1, } );
}
if ( !$place ) {
$place = MT::Placement->new;
@@ -310,10 +319,7 @@
# Delete all the secondary placements, so each of the remaining
# iterations of the loop make a brand new placement.
my @old_places = MT::Placement->load(
- { entry_id => $entry->id,
- is_primary => 0,
- }
- );
+ { entry_id => $entry->id, is_primary => 0, } );
for my $place (@old_places) {
$place->remove;
}
@@ -391,8 +397,7 @@
);
$entry->allow_comments( $item->{mt_allow_comments} )
if exists $item->{mt_allow_comments};
- $entry->title( $item->{title} )
- if exists $item->{title};
+ $entry->title( $item->{title} ) if exists $item->{title};
$class->_apply_basename( $entry, $item, \%param );
@@ -488,6 +493,21 @@
else {
( $blog_id, $user, $pass, $item, $publish ) = @_;
}
+
+ _validate_params( [ $blog_id, $user, $pass, $publish ] ) or return;
+ my $values;
+ foreach my $k ( keys %$item ) {
+ if ( 'categories' eq $k || 'mt_tb_ping_urls' eq $k ) {
+
+ # XMLRPC supports categories array and mt_tb_ping_urls array
+ _validate_params( \@{ $item->{$k} } ) or return;
+ }
+ else {
+ push @$values, $item->{$k};
+ }
+ }
+ _validate_params( \@$values ) or return;
+
$class->_new_entry(
blog_id => $blog_id,
user => $user,
@@ -500,6 +520,21 @@
sub newPage {
my $class = shift;
my ( $blog_id, $user, $pass, $item, $publish ) = @_;
+
+ _validate_params( [ $blog_id, $user, $pass, $publish ] ) or return;
+ my $values;
+ foreach my $k ( keys %$item ) {
+ if ( 'mt_tb_ping_urls' eq $k ) {
+
+ # XMLRPC supports mt_tb_ping_urls array
+ _validate_params( \@{ $item->{$k} } ) or return;
+ }
+ else {
+ push @$values, $item->{$k};
+ }
+ }
+ _validate_params( \@$values ) or return;
+
$class->_new_entry(
blog_id => $blog_id,
user => $user,
@@ -648,6 +683,21 @@
else {
( $entry_id, $user, $pass, $item, $publish ) = @_;
}
+
+ _validate_params( [ $entry_id, $user, $pass, $publish ] ) or return;
+ my $values;
+ foreach my $k ( keys %$item ) {
+ if ( 'categories' eq $k || 'mt_tb_ping_urls' eq $k ) {
+
+ # XMLRPC supports categories array and mt_tb_ping_urls array
+ _validate_params( \@{ $item->{$k} } ) or return;
+ }
+ else {
+ push @$values, $item->{$k};
+ }
+ }
+ _validate_params( \@$values ) or return;
+
$class->_edit_entry(
entry_id => $entry_id,
user => $user,
@@ -660,6 +710,22 @@
sub editPage {
my $class = shift;
my ( $blog_id, $entry_id, $user, $pass, $item, $publish ) = @_;
+
+ _validate_params( [ $blog_id, $entry_id, $user, $pass, $publish ] )
+ or return;
+ my $values;
+ foreach my $k ( keys %$item ) {
+ if ( 'mt_tb_ping_urls' eq $k ) {
+
+ # XMLRPC supports mt_tb_ping_urls array
+ _validate_params( \@{ $item->{$k} } ) or return;
+ }
+ else {
+ push @$values, $item->{$k};
+ }
+ }
+ _validate_params( \@$values ) or return;
+
$class->_edit_entry(
blog_id => $blog_id,
entry_id => $entry_id,
@@ -680,6 +746,9 @@
$class = __PACKAGE__;
}
my ( $appkey, $user, $pass ) = @_;
+
+ _validate_params( [ $user, $pass ] ) or return;
+
my $mt = MT::XMLRPCServer::Util::mt_new(); ## Will die if MT->new fails.
my ($author) = $class->_login( $user, $pass );
die _fault( MT->translate("Invalid login") ) unless $author;
@@ -728,6 +797,9 @@
$class = __PACKAGE__;
}
my ( $appkey, $user, $pass ) = @_;
+
+ _validate_params( [ $user, $pass ] ) or return;
+
my $mt = MT::XMLRPCServer::Util::mt_new(); ## Will die if MT->new fails.
my ($author) = $class->_login( $user, $pass );
die _fault( MT->translate("Invalid login") ) unless $author;
@@ -753,8 +825,7 @@
die _fault( MT->translate("Invalid login") ) unless $author;
die _fault( MT->translate("Permission denied.") )
if !$author->is_superuser
- && ( !$perms
- || !$perms->can_do('get_entries_via_xmlrpc_server') );
+ && ( !$perms || !$perms->can_do('get_entries_via_xmlrpc_server') );
my $iter = MT->model($obj_type)->load_iter(
{ blog_id => $blog_id },
{ 'sort' => 'authored_on',
@@ -820,6 +891,9 @@
else {
( $blog_id, $user, $pass, $num ) = @_;
}
+
+ _validate_params( [ $blog_id, $user, $pass, $num ] ) or return;
+
$class->_get_entries(
blog_id => $blog_id,
user => $user,
@@ -831,6 +905,9 @@
sub getRecentPostTitles {
my $class = shift;
my ( $blog_id, $user, $pass, $num ) = @_;
+
+ _validate_params( [ $blog_id, $user, $pass, $num ] ) or return;
+
$class->_get_entries(
blog_id => $blog_id,
user => $user,
@@ -843,6 +920,9 @@
sub getPages {
my $class = shift;
my ( $blog_id, $user, $pass ) = @_;
+
+ _validate_params( [ $blog_id, $user, $pass ] ) or return;
+
$class->_get_entries(
blog_id => $blog_id,
user => $user,
@@ -879,16 +959,13 @@
# Rebuild archives
if (%recipe) {
- $mt->rebuild_archives(
- Blog => $blog,
- Recipe => \%recipe,
- ) or die _fault( $class->errstr );
+ $mt->rebuild_archives( Blog => $blog, Recipe => \%recipe, )
+ or die _fault( $class->errstr );
}
# Rebuild index files
if ( $mt->config('RebuildAtDelete') ) {
- $mt->rebuild_indexes( Blog => $blog )
- or die _fault( $class->errstr );
+ $mt->rebuild_indexes( Blog => $blog ) or die _fault( $class->errstr );
}
$mt->log(
@@ -915,6 +992,9 @@
$class = __PACKAGE__;
}
my ( $appkey, $entry_id, $user, $pass, $publish ) = @_;
+
+ _validate_params( [ $entry_id, $user, $pass, $publish ] ) or return;
+
$class->_delete_entry(
entry_id => $entry_id,
user => $user,
@@ -926,6 +1006,9 @@
sub deletePage {
my $class = shift;
my ( $blog_id, $user, $pass, $entry_id ) = @_;
+
+ _validate_params( [ $blog_id, $user, $pass, $entry_id ] ) or return;
+
$class->_delete_entry(
blog_id => $blog_id,
entry_id => $entry_id,
@@ -954,8 +1037,8 @@
die _fault( MT->translate("Not allowed to get entry") )
if !$author->is_superuser
&& ( !$perms || !$perms->can_edit_entry( $entry, $author ) );
- my $co = sprintf "%04d%02d%02dT%02d:%02d:%02d",
- unpack 'A4A2A2A2A2A2', $entry->authored_on;
+ my $co = sprintf "%04d%02d%02dT%02d:%02d:%02d", unpack 'A4A2A2A2A2A2',
+ $entry->authored_on;
my $link = $entry->permalink;
require MT::Tag;
my $delim = chr( $author->entry_prefs->{tag_delim} );
@@ -999,12 +1082,18 @@
sub getPost {
my $class = shift;
my ( $entry_id, $user, $pass ) = @_;
+
+ _validate_params( [ $entry_id, $user, $pass ] ) or return;
+
$class->_get_entry( entry_id => $entry_id, user => $user, pass => $pass );
}
sub getPage {
my $class = shift;
my ( $blog_id, $entry_id, $user, $pass ) = @_;
+
+ _validate_params( [ $blog_id, $entry_id, $user, $pass ] ) or return;
+
$class->_get_entry(
blog_id => $blog_id,
entry_id => $entry_id,
@@ -1020,9 +1109,8 @@
'metaWeblog.getPost', 'metaWeblog.newPost', 'metaWeblog.editPost',
'metaWeblog.getRecentPosts', 'metaWeblog.newMediaObject',
'metaWeblog.getCategories', 'metaWeblog.deletePost',
- 'metaWeblog.getUsersBlogs',
- 'wp.newPage', 'wp.getPages', 'wp.getPage', 'wp.editPage',
- 'wp.deletePage',
+ 'metaWeblog.getUsersBlogs', 'wp.newPage', 'wp.getPages', 'wp.getPage',
+ 'wp.editPage', 'wp.deletePage',
# not yet supported: metaWeblog.getTemplate, metaWeblog.setTemplate
'mt.getCategoryList', 'mt.setPostCategories', 'mt.getPostCategories',
@@ -1056,6 +1144,9 @@
sub getCategoryList {
my $class = shift;
my ( $blog_id, $user, $pass ) = @_;
+
+ _validate_params( [ $blog_id, $user, $pass ] ) or return;
+
my $mt = MT::XMLRPCServer::Util::mt_new(); ## Will die if MT->new fails.
my ( $author, $perms ) = $class->_login( $user, $pass, $blog_id );
die _fault( MT->translate("Invalid login") ) unless $author;
@@ -1080,13 +1171,15 @@
sub getCategories {
my $class = shift;
my ( $blog_id, $user, $pass ) = @_;
+
+ _validate_params( [ $blog_id, $user, $pass ] ) or return;
+
my $mt = MT::XMLRPCServer::Util::mt_new(); ## Will die if MT->new fails.
my ( $author, $perms ) = $class->_login( $user, $pass, $blog_id );
die _fault( MT->translate("Invalid login") ) unless $author;
die _fault( MT->translate("Permission denied.") )
if !$author->is_superuser
- && ( !$perms
- || !$perms->can_do('get_categories_via_xmlrpc_server') );
+ && ( !$perms || !$perms->can_do('get_categories_via_xmlrpc_server') );
require MT::Category;
my $iter = MT::Category->load_iter( { blog_id => $blog_id } );
my @data;
@@ -1117,13 +1210,15 @@
sub getTagList {
my $class = shift;
my ( $blog_id, $user, $pass ) = @_;
+
+ _validate_params( [ $blog_id, $user, $pass ] ) or return;
+
my $mt = MT::XMLRPCServer::Util::mt_new(); ## Will die if MT->new fails.
my ( $author, $perms ) = $class->_login( $user, $pass, $blog_id );
die _fault( MT->translate("Invalid login") ) unless $author;
die _fault( MT->translate("Permission denied.") )
if !$author->is_superuser
- && ( !$perms
- || !$perms->can_do('get_tag_list_via_xmlrpc_server') );
+ && ( !$perms || !$perms->can_do('get_tag_list_via_xmlrpc_server') );
require MT::Tag;
require MT::ObjectTag;
my $iter = MT::Tag->load_iter(
@@ -1149,6 +1244,9 @@
sub getPostCategories {
my $class = shift;
my ( $entry_id, $user, $pass ) = @_;
+
+ _validate_params( [ $entry_id, $user, $pass ] ) or return;
+
my $mt = MT::XMLRPCServer::Util::mt_new(); ## Will die if MT->new fails.
require MT::Entry;
my $entry = MT::Entry->load($entry_id)
@@ -1179,6 +1277,12 @@
sub setPostCategories {
my $class = shift;
my ( $entry_id, $user, $pass, $cats ) = @_;
+
+ _validate_params( [ $entry_id, $user, $pass ] ) or return;
+ foreach my $c (@$cats) {
+ _validate_params( [ values %$c ] ) or return;
+ }
+
my $mt = MT::XMLRPCServer::Util::mt_new(); ## Will die if MT->new fails.
require MT::Entry;
require MT::Placement;
@@ -1227,11 +1331,13 @@
sub getTrackbackPings {
my $class = shift;
my ($entry_id) = @_;
+
+ _validate_params( [$entry_id] ) or return;
+
require MT::Trackback;
require MT::TBPing;
my $mt = MT::XMLRPCServer::Util::mt_new(); ## Will die if MT->new fails.
- my $tb = MT::Trackback->load( { entry_id => $entry_id } )
- or return [];
+ my $tb = MT::Trackback->load( { entry_id => $entry_id } ) or return [];
my $iter = MT::TBPing->load_iter( { tb_id => $tb->id } );
my @data;
@@ -1249,6 +1355,9 @@
sub publishPost {
my $class = shift;
my ( $entry_id, $user, $pass ) = @_;
+
+ _validate_params( [ $entry_id, $user, $pass ] ) or return;
+
my $mt = MT::XMLRPCServer::Util::mt_new(); ## Will die if MT->new fails.
require MT::Entry;
my $entry = MT::Entry->load($entry_id)
@@ -1269,6 +1378,8 @@
my $class = shift;
my ( $user, $pass ) = @_;
+ _validate_params( [ $user, $pass ] ) or return;
+
my $mt = MT::XMLRPCServer::Util::mt_new();
my $author = $class->_login( $user, $pass );
die _fault( MT->translate("Invalid login") ) unless $author;
@@ -1282,6 +1393,8 @@
my $class = shift;
my ( $blog_id, $user, $pass ) = @_;
+ _validate_params( [ $blog_id, $user, $pass ] ) or return;
+
my $mt = MT::XMLRPCServer::Util::mt_new();
my $author = $class->_login( $user, $pass );
die _fault( MT->translate("Invalid login") ) unless $author;
@@ -1318,8 +1431,7 @@
if ( $entry && $entry->authored_on <= $now ) {
$entry->status( MT::Entry::RELEASE() );
$entry->discover_tb_from_entry();
- $entry->save
- or die $entry->errstr;
+ $entry->save or die $entry->errstr;
$types{ $entry->class } = 1;
start_background_task(
@@ -1336,18 +1448,17 @@
$blog->save if $changed && ( keys %types );
if ($changed) {
- $mt->rebuild_indexes( Blog => $blog )
- or die $mt->errstr;
+ $mt->rebuild_indexes( Blog => $blog ) or die $mt->errstr;
}
- { responseCode => 'success',
- publishedCount => $total_changed,
- };
+ { responseCode => 'success', publishedCount => $total_changed, };
}
sub getNextScheduled {
my $class = shift;
my ( $user, $pass ) = @_;
+ _validate_params( [ $user, $pass ] ) or return;
+
my $mt = MT::XMLRPCServer::Util::mt_new();
my $author = $class->_login( $user, $pass );
die _fault( MT->translate("Invalid login") ) unless $author;
@@ -1360,6 +1471,11 @@
sub setRemoteAuthToken {
my $class = shift;
my ( $user, $pass, $remote_auth_username, $remote_auth_token ) = @_;
+
+ _validate_params(
+ [ $user, $pass, $remote_auth_username, $remote_auth_token ] )
+ or return;
+
my $mt = MT::XMLRPCServer::Util::mt_new(); ## Will die if MT->new fails.
my ($author) = $class->_login( $user, $pass );
die _fault( MT->translate("Invalid login") ) unless $author;
@@ -1372,13 +1488,16 @@
sub newMediaObject {
my $class = shift;
my ( $blog_id, $user, $pass, $file ) = @_;
+
+ _validate_params( [ $blog_id, $user, $pass ] ) or return;
+ _validate_params( [ values %$file ] ) or return;
+
my $mt = MT::XMLRPCServer::Util::mt_new(); ## Will die if MT->new fails.
my ( $author, $perms ) = $class->_login( $user, $pass, $blog_id );
die _fault( MT->translate("Invalid login") ) unless $author;
die _fault( MT->translate("Not allowed to upload files") )
if !$author->is_superuser
- && ( !$perms
- || !$perms->can_do('upload_asset_via_xmlrpc_server') );
+ && ( !$perms || !$perms->can_do('upload_asset_via_xmlrpc_server') );
require MT::Blog;
require File::Spec;
@@ -1418,15 +1537,15 @@
}
my $local_file = File::Spec->catfile( $blog->site_path, $file->{name} );
- my $ext
- = ( File::Basename::fileparse( $local_file, qr/[A-Za-z0-9]+$/ ) )[2];
+ my $ext = ( File::Basename::fileparse( $local_file, qr/[A-Za-z0-9]+$/ ) )[2];
require MT::Asset::Image;
if ( MT::Asset::Image->can_handle($ext) ) {
require MT::Image;
my $fh;
my $data = $file->{bits};
open( $fh, "+<", \$data );
- close($fh), die _fault(
+ close($fh),
+ die _fault(
MT->translate(
"Saving [_1] failed: [_2]",
$file->{name},
@@ -1471,8 +1590,7 @@
my $asset_pkg = MT::Asset->handler_for_file($local_basename);
my $is_image = 0;
if ( defined($w) && defined($h) ) {
- $is_image = 1
- if $asset_pkg->isa('MT::Asset::Image');
+ $is_image = 1 if $asset_pkg->isa('MT::Asset::Image');
}
else {