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 {
 

Reply via email to