Browse code

Fixes #1090 - Be more resilient to a server sending random data in ?lifecycle response

Florent Viard authored on 2020/04/20 22:48:21
Showing 2 changed files
... ...
@@ -529,23 +529,34 @@ class S3(object):
529 529
     def expiration_info(self, uri, bucket_location = None):
530 530
         bucket = uri.bucket()
531 531
 
532
-        request = self.create_request("BUCKET_LIST", bucket = bucket,
533
-                                      uri_params = {'lifecycle': None})
532
+        request = self.create_request("BUCKET_LIST", bucket=bucket,
533
+                                      uri_params={'lifecycle': None})
534 534
         try:
535 535
             response = self.send_request(request)
536
-            response['prefix'] = getTextFromXml(response['data'], ".//Rule//Prefix")
537
-            response['date'] = getTextFromXml(response['data'], ".//Rule//Expiration//Date")
538
-            response['days'] = getTextFromXml(response['data'], ".//Rule//Expiration//Days")
539
-            return response
540 536
         except S3Error as e:
541 537
             if e.status == 404:
542
-                debug("Could not get /?lifecycle - lifecycle probably not configured for this bucket")
538
+                debug("Could not get /?lifecycle - lifecycle probably not "
539
+                      "configured for this bucket")
543 540
                 return None
544 541
             elif e.status == 501:
545
-                debug("Could not get /?lifecycle - lifecycle support not implemented by the server")
542
+                debug("Could not get /?lifecycle - lifecycle support not "
543
+                      "implemented by the server")
546 544
                 return None
547 545
             raise
548 546
 
547
+        root_tag_name = getRootTagName(response['data'])
548
+        if root_tag_name != "LifecycleConfiguration":
549
+            debug("Could not get /?lifecycle - unexpected xml response: "
550
+                  "%s", root_tag_name)
551
+            return None
552
+        response['prefix'] = getTextFromXml(response['data'],
553
+                                            ".//Rule//Prefix")
554
+        response['date'] = getTextFromXml(response['data'],
555
+                                          ".//Rule//Expiration//Date")
556
+        response['days'] = getTextFromXml(response['data'],
557
+                                          ".//Rule//Expiration//Days")
558
+        return response
559
+
549 560
     def expiration_set(self, uri, bucket_location = None):
550 561
         if self.config.expiry_date and self.config.expiry_days:
551 562
              raise ParameterError("Expect either --expiry-day or --expiry-date")
... ...
@@ -977,7 +977,7 @@ def cmd_info(args):
977 977
                     expiration_desc = "Expiration Rule: "
978 978
                     if expiration['prefix'] == "":
979 979
                         expiration_desc += "all objects in this bucket "
980
-                    else:
980
+                    elif expiration['prefix'] is not None:
981 981
                         expiration_desc += "objects with key prefix '" + expiration['prefix'] + "' "
982 982
                     expiration_desc += "will expire in '"
983 983
                     if expiration['days']: