Compare commits
No commits in common. "18d108cfc25e891c0ef4f9f632d7a271ae0de71d" and "dce260245a7ddaad28fa7715d8390db1b9268c60" have entirely different histories.
18d108cfc2
...
dce260245a
2
.gitignore
vendored
2
.gitignore
vendored
@ -4,5 +4,3 @@
|
|||||||
/oauthlib-2.0.1.tar.gz
|
/oauthlib-2.0.1.tar.gz
|
||||||
/v2.1.0.tar.gz
|
/v2.1.0.tar.gz
|
||||||
/oauthlib-3.0.2.tar.gz
|
/oauthlib-3.0.2.tar.gz
|
||||||
/oauthlib-3.1.0.tar.gz
|
|
||||||
/oauthlib-3.1.1.tar.gz
|
|
||||||
|
@ -1,282 +0,0 @@
|
|||||||
From 6284bb10c4b67a9254cc6452efc99a4174607a36 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jakub Hrozek <jhrozek@redhat.com>
|
|
||||||
Date: Wed, 23 Jun 2021 22:37:42 +0200
|
|
||||||
Subject: [PATCH] Rip out RSA-SHA1
|
|
||||||
|
|
||||||
---
|
|
||||||
oauthlib/oauth1/__init__.py | 2 --
|
|
||||||
oauthlib/oauth1/rfc5849/__init__.py | 2 ++
|
|
||||||
oauthlib/oauth1/rfc5849/endpoints/base.py | 11 +++---
|
|
||||||
oauthlib/oauth1/rfc5849/signature.py | 37 +++------------------
|
|
||||||
tests/oauth1/rfc5849/endpoints/test_base.py | 9 -----
|
|
||||||
tests/oauth1/rfc5849/test_client.py | 17 ++++------
|
|
||||||
tests/oauth1/rfc5849/test_signatures.py | 33 +++++++++---------
|
|
||||||
7 files changed, 36 insertions(+), 75 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/oauthlib/oauth1/__init__.py b/oauthlib/oauth1/__init__.py
|
|
||||||
index 07ef422..5573ed6 100644
|
|
||||||
--- a/oauthlib/oauth1/__init__.py
|
|
||||||
+++ b/oauthlib/oauth1/__init__.py
|
|
||||||
@@ -10,8 +10,6 @@ from .rfc5849 import (SIGNATURE_HMAC,
|
|
||||||
SIGNATURE_HMAC_SHA1,
|
|
||||||
SIGNATURE_HMAC_SHA256,
|
|
||||||
SIGNATURE_HMAC_SHA512,
|
|
||||||
- SIGNATURE_RSA,
|
|
||||||
- SIGNATURE_RSA_SHA1,
|
|
||||||
SIGNATURE_RSA_SHA256,
|
|
||||||
SIGNATURE_RSA_SHA512,
|
|
||||||
SIGNATURE_PLAINTEXT)
|
|
||||||
diff --git a/oauthlib/oauth1/rfc5849/__init__.py b/oauthlib/oauth1/rfc5849/__init__.py
|
|
||||||
index c559251..1a56728 100644
|
|
||||||
--- a/oauthlib/oauth1/rfc5849/__init__.py
|
|
||||||
+++ b/oauthlib/oauth1/rfc5849/__init__.py
|
|
||||||
@@ -78,6 +78,8 @@ class Client:
|
|
||||||
SIGNATURE_HMAC_SHA1: signature.sign_hmac_sha1_with_client,
|
|
||||||
SIGNATURE_HMAC_SHA256: signature.sign_hmac_sha256_with_client,
|
|
||||||
SIGNATURE_HMAC_SHA512: signature.sign_hmac_sha512_with_client,
|
|
||||||
+ # sign_rsa_sha1_with_client actually points out to a dummy method
|
|
||||||
+ # that just throws an exception
|
|
||||||
SIGNATURE_RSA_SHA1: signature.sign_rsa_sha1_with_client,
|
|
||||||
SIGNATURE_RSA_SHA256: signature.sign_rsa_sha256_with_client,
|
|
||||||
SIGNATURE_RSA_SHA512: signature.sign_rsa_sha512_with_client,
|
|
||||||
diff --git a/oauthlib/oauth1/rfc5849/endpoints/base.py b/oauthlib/oauth1/rfc5849/endpoints/base.py
|
|
||||||
index 3a8c267..f1694d4 100644
|
|
||||||
--- a/oauthlib/oauth1/rfc5849/endpoints/base.py
|
|
||||||
+++ b/oauthlib/oauth1/rfc5849/endpoints/base.py
|
|
||||||
@@ -180,9 +180,12 @@ class BaseEndpoint:
|
|
||||||
description='Invalid nonce format.')
|
|
||||||
|
|
||||||
def _check_signature(self, request, is_token_request=False):
|
|
||||||
+ # ---- RSA-SHA1 is not allowed ------
|
|
||||||
+ if request.signature_method == SIGNATURE_RSA_SHA1:
|
|
||||||
+ raise ValueError("Using RSA-SHA1 is deprecated, use HMAC-SHA1 or a stronger RSA-SHA***")
|
|
||||||
+
|
|
||||||
# ---- RSA Signature verification ----
|
|
||||||
- if request.signature_method == SIGNATURE_RSA_SHA1 or \
|
|
||||||
- request.signature_method == SIGNATURE_RSA_SHA256 or \
|
|
||||||
+ if request.signature_method == SIGNATURE_RSA_SHA256 or \
|
|
||||||
request.signature_method == SIGNATURE_RSA_SHA512:
|
|
||||||
# RSA-based signature method
|
|
||||||
|
|
||||||
@@ -192,9 +195,7 @@ class BaseEndpoint:
|
|
||||||
rsa_key = self.request_validator.get_rsa_key(
|
|
||||||
request.client_key, request)
|
|
||||||
|
|
||||||
- if request.signature_method == SIGNATURE_RSA_SHA1:
|
|
||||||
- valid_signature = signature.verify_rsa_sha1(request, rsa_key)
|
|
||||||
- elif request.signature_method == SIGNATURE_RSA_SHA256:
|
|
||||||
+ if request.signature_method == SIGNATURE_RSA_SHA256:
|
|
||||||
valid_signature = signature.verify_rsa_sha256(request, rsa_key)
|
|
||||||
elif request.signature_method == SIGNATURE_RSA_SHA512:
|
|
||||||
valid_signature = signature.verify_rsa_sha512(request, rsa_key)
|
|
||||||
diff --git a/oauthlib/oauth1/rfc5849/signature.py b/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
index a370ccd..d8f2761 100644
|
|
||||||
--- a/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
+++ b/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
@@ -561,7 +561,6 @@ def _get_jwt_rsa_algorithm(hash_algorithm_name: str):
|
|
||||||
# PyJWT has some nice pycrypto/cryptography abstractions
|
|
||||||
import jwt.algorithms as jwt_algorithms
|
|
||||||
m = {
|
|
||||||
- 'SHA-1': jwt_algorithms.hashes.SHA1,
|
|
||||||
'SHA-256': jwt_algorithms.hashes.SHA256,
|
|
||||||
'SHA-512': jwt_algorithms.hashes.SHA512,
|
|
||||||
}
|
|
||||||
@@ -727,44 +726,16 @@ def _verify_rsa(hash_algorithm_name: str,
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
-# ==== RSA-SHA1 ==================================================
|
|
||||||
+# ==== RSA-SHA1 DEPRECATED ================================================
|
|
||||||
|
|
||||||
def sign_rsa_sha1_with_client(sig_base_str, client):
|
|
||||||
- # For some reason, this function originally accepts both str and bytes.
|
|
||||||
- # This behaviour is preserved here. But won't be done for the newer
|
|
||||||
- # sign_rsa_sha256_with_client and sign_rsa_sha512_with_client functions,
|
|
||||||
- # which will only accept strings. The function to calculate a
|
|
||||||
- # "signature base string" always produces a string, so it is not clear
|
|
||||||
- # why support for bytes would ever be needed.
|
|
||||||
- sig_base_str = sig_base_str.decode('ascii')\
|
|
||||||
- if isinstance(sig_base_str, bytes) else sig_base_str
|
|
||||||
-
|
|
||||||
- return _sign_rsa('SHA-1', sig_base_str, client.rsa_key)
|
|
||||||
-
|
|
||||||
+ raise ValueError("RSA-SHA1 is deprecated, use a stronger hash or HMAC-SHA1")
|
|
||||||
|
|
||||||
def verify_rsa_sha1(request, rsa_public_key: str):
|
|
||||||
- return _verify_rsa('SHA-1', request, rsa_public_key)
|
|
||||||
-
|
|
||||||
+ raise ValueError("RSA-SHA1 is deprecated, use a stronger hash or HMAC-SHA1")
|
|
||||||
|
|
||||||
def sign_rsa_sha1(base_string, rsa_private_key):
|
|
||||||
- """
|
|
||||||
- Deprecated function for calculating a RSA-SHA1 signature.
|
|
||||||
-
|
|
||||||
- This function has been replaced by invoking ``sign_rsa`` with "SHA-1"
|
|
||||||
- as the hash algorithm name.
|
|
||||||
-
|
|
||||||
- This function was invoked by sign_rsa_sha1_with_client and
|
|
||||||
- test_signatures.py, but does any application invoke it directly? If not,
|
|
||||||
- it can be removed.
|
|
||||||
- """
|
|
||||||
- warnings.warn('use _sign_rsa("SHA-1", ...) instead of sign_rsa_sha1',
|
|
||||||
- DeprecationWarning)
|
|
||||||
-
|
|
||||||
- if isinstance(base_string, bytes):
|
|
||||||
- base_string = base_string.decode('ascii')
|
|
||||||
-
|
|
||||||
- return _sign_rsa('SHA-1', base_string, rsa_private_key)
|
|
||||||
-
|
|
||||||
+ raise ValueError("RSA-SHA1 is deprecated, use a stronger hash or HMAC-SHA1")
|
|
||||||
|
|
||||||
# ==== RSA-SHA256 ================================================
|
|
||||||
|
|
||||||
diff --git a/tests/oauth1/rfc5849/endpoints/test_base.py b/tests/oauth1/rfc5849/endpoints/test_base.py
|
|
||||||
index e87f359..2d0d213 100644
|
|
||||||
--- a/tests/oauth1/rfc5849/endpoints/test_base.py
|
|
||||||
+++ b/tests/oauth1/rfc5849/endpoints/test_base.py
|
|
||||||
@@ -390,15 +390,6 @@ class SignatureVerificationTest(TestCase):
|
|
||||||
r = self.e._create_request(self.uri, 'GET', sig, URLENCODED)
|
|
||||||
self.assertTrue(self.e._check_signature(r))
|
|
||||||
|
|
||||||
- def test_rsa_signature(self):
|
|
||||||
- rsa_sig = ("fxFvCx33oKlR9wDquJ%2FPsndFzJphyBa3RFPPIKi3flqK%2BJ7yIrMVbH"
|
|
||||||
- "YTM%2FLHPc7NChWz4F4%2FzRA%2BDN1k08xgYGSBoWJUOW6VvOQ6fbYhMA"
|
|
||||||
- "FkOGYbuGDbje487XMzsAcv6ZjqZHCROSCk5vofgLk2SN7RZ3OrgrFzf4in"
|
|
||||||
- "xetClqA%3D")
|
|
||||||
- sig = self.sig % (rsa_sig, "RSA-SHA1")
|
|
||||||
- r = self.e._create_request(self.uri, 'GET', sig, URLENCODED)
|
|
||||||
- self.assertTrue(self.e._check_signature(r))
|
|
||||||
-
|
|
||||||
def test_plaintext_signature(self):
|
|
||||||
plain_sig = "super%252520secret%26even%252520more%252520secret"
|
|
||||||
sig = self.sig % (plain_sig, "PLAINTEXT")
|
|
||||||
diff --git a/tests/oauth1/rfc5849/test_client.py b/tests/oauth1/rfc5849/test_client.py
|
|
||||||
index f7c997f..d167652 100644
|
|
||||||
--- a/tests/oauth1/rfc5849/test_client.py
|
|
||||||
+++ b/tests/oauth1/rfc5849/test_client.py
|
|
||||||
@@ -2,7 +2,7 @@
|
|
||||||
from oauthlib.common import Request
|
|
||||||
from oauthlib.oauth1 import (
|
|
||||||
SIGNATURE_HMAC_SHA1, SIGNATURE_HMAC_SHA256, SIGNATURE_PLAINTEXT,
|
|
||||||
- SIGNATURE_RSA, SIGNATURE_TYPE_BODY, SIGNATURE_TYPE_QUERY,
|
|
||||||
+ SIGNATURE_RSA_SHA256, SIGNATURE_TYPE_BODY, SIGNATURE_TYPE_QUERY,
|
|
||||||
)
|
|
||||||
from oauthlib.oauth1.rfc5849 import Client
|
|
||||||
|
|
||||||
@@ -75,9 +75,9 @@ class ClientConstructorTests(TestCase):
|
|
||||||
client.SIGNATURE_METHODS[client.signature_method])
|
|
||||||
|
|
||||||
def test_rsa(self):
|
|
||||||
- client = Client('client_key', signature_method=SIGNATURE_RSA)
|
|
||||||
+ client = Client('client_key', signature_method=SIGNATURE_RSA_SHA256)
|
|
||||||
# instance is using the correct signer method
|
|
||||||
- self.assertEqual(Client.SIGNATURE_METHODS[SIGNATURE_RSA],
|
|
||||||
+ self.assertEqual(Client.SIGNATURE_METHODS[SIGNATURE_RSA_SHA256],
|
|
||||||
client.SIGNATURE_METHODS[client.signature_method])
|
|
||||||
# don't need an RSA key to instantiate
|
|
||||||
self.assertIsNone(client.rsa_key)
|
|
||||||
@@ -124,16 +124,13 @@ class SignatureMethodTest(TestCase):
|
|
||||||
"LVduVgh4v5yLT\nGa6FHdjGPcfajt+nrpB1n8UQBEH9ZxniokR/IPv"
|
|
||||||
"dMlxqXA==\n-----END RSA PRIVATE KEY-----"
|
|
||||||
)
|
|
||||||
- client = Client('client_key', signature_method=SIGNATURE_RSA,
|
|
||||||
+ client = Client('client_key', signature_method=SIGNATURE_RSA_SHA256,
|
|
||||||
rsa_key=private_key, timestamp='1234567890', nonce='abc')
|
|
||||||
u, h, b = client.sign('http://example.com')
|
|
||||||
correct = ('OAuth oauth_nonce="abc", oauth_timestamp="1234567890", '
|
|
||||||
- 'oauth_version="1.0", oauth_signature_method="RSA-SHA1", '
|
|
||||||
+ 'oauth_version="1.0", oauth_signature_method="RSA-SHA256", '
|
|
||||||
'oauth_consumer_key="client_key", '
|
|
||||||
- 'oauth_signature="ktvzkUhtrIawBcq21DRJrAyysTc3E1Zq5GdGu8EzH'
|
|
||||||
- 'OtbeaCmOBDLGHAcqlm92mj7xp5E1Z6i2vbExPimYAJL7FzkLnkRE5YEJR4'
|
|
||||||
- 'rNtIgAf1OZbYsIUmmBO%2BCLuStuu5Lg3tAluwC7XkkgoXCBaRKT1mUXzP'
|
|
||||||
- 'HJILzZ8iFOvS6w5E%3D"')
|
|
||||||
+ 'oauth_signature="hJE2IGqCn3bw7ecu6psnsImrvERhTd667aIENzWbzdRGxEWwvAwJvWWCffD8P0Ox9IEu3gKD%2FzYdr36tBhW%2FMvdFsOAr4F41ojznv1urY6%2FD9FRs1py9dYuj1vdFYFUzziMBDv2w2emidDk8PqfHT1we5%2FIcH%2FKNCjMbkQgxsqE%3D"')
|
|
||||||
self.assertEqual(h['Authorization'], correct)
|
|
||||||
|
|
||||||
def test_plaintext_method(self):
|
|
||||||
@@ -155,7 +152,7 @@ class SignatureMethodTest(TestCase):
|
|
||||||
self.assertRaises(ValueError, client.sign, 'http://example.com')
|
|
||||||
|
|
||||||
def test_rsa_no_key(self):
|
|
||||||
- client = Client('client_key', signature_method=SIGNATURE_RSA)
|
|
||||||
+ client = Client('client_key', signature_method=SIGNATURE_RSA_SHA256)
|
|
||||||
self.assertRaises(ValueError, client.sign, 'http://example.com')
|
|
||||||
|
|
||||||
def test_register_method(self):
|
|
||||||
diff --git a/tests/oauth1/rfc5849/test_signatures.py b/tests/oauth1/rfc5849/test_signatures.py
|
|
||||||
index 3e84f24..c505a38 100644
|
|
||||||
--- a/tests/oauth1/rfc5849/test_signatures.py
|
|
||||||
+++ b/tests/oauth1/rfc5849/test_signatures.py
|
|
||||||
@@ -640,18 +640,20 @@ GLYT3Jw1Lfb1bbuck9Y0JsRJO7uydWUbxXyZ+8YaDfE2NMw7sh2vAgMBAAE=
|
|
||||||
|
|
||||||
def test_sign_rsa_sha1_with_client(self):
|
|
||||||
"""
|
|
||||||
- Test sign and verify with RSA-SHA1.
|
|
||||||
+ Test that sign and verify with RSA-SHA1 throws an exception
|
|
||||||
"""
|
|
||||||
- self.assertEqual(
|
|
||||||
- self.expected_signature_rsa_sha1,
|
|
||||||
- sign_rsa_sha1_with_client(self.eg_signature_base_string,
|
|
||||||
- self.rsa_private_client))
|
|
||||||
- self.assertTrue(verify_rsa_sha1(
|
|
||||||
- MockRequest('POST',
|
|
||||||
- 'http://example.com/request',
|
|
||||||
- self.eg_params,
|
|
||||||
- self.expected_signature_rsa_sha1),
|
|
||||||
- self.rsa_public_client.rsa_key))
|
|
||||||
+ self.assertRaises(ValueError,
|
|
||||||
+ sign_rsa_sha1_with_client,
|
|
||||||
+ self.eg_signature_base_string,
|
|
||||||
+ self.rsa_private_client)
|
|
||||||
+
|
|
||||||
+ self.assertRaises(ValueError,
|
|
||||||
+ verify_rsa_sha1,
|
|
||||||
+ MockRequest('POST',
|
|
||||||
+ 'http://example.com/request',
|
|
||||||
+ self.eg_params,
|
|
||||||
+ self.expected_signature_rsa_sha1),
|
|
||||||
+ self.rsa_public_client.rsa_key)
|
|
||||||
|
|
||||||
def test_sign_rsa_sha256_with_client(self):
|
|
||||||
"""
|
|
||||||
@@ -707,7 +709,6 @@ MmgDHR2tt8KeYTSgfU+BAkBcaVF91EQ7VXhvyABNYjeYP7lU7orOgdWMa/zbLXSU
|
|
||||||
''')
|
|
||||||
|
|
||||||
for functions in [
|
|
||||||
- (sign_rsa_sha1_with_client, verify_rsa_sha1),
|
|
||||||
(sign_rsa_sha256_with_client, verify_rsa_sha256),
|
|
||||||
(sign_rsa_sha512_with_client, verify_rsa_sha512),
|
|
||||||
]:
|
|
||||||
@@ -757,12 +758,12 @@ MmgDHR2tt8KeYTSgfU+BAkBcaVF91EQ7VXhvyABNYjeYP7lU7orOgdWMa/zbLXSU
|
|
||||||
|
|
||||||
for bad_value in [None, '', 'foobar']:
|
|
||||||
self.assertRaises(ValueError,
|
|
||||||
- sign_rsa_sha1_with_client,
|
|
||||||
+ sign_rsa_sha256_with_client,
|
|
||||||
self.eg_signature_base_string,
|
|
||||||
MockClient(rsa_key=bad_value))
|
|
||||||
|
|
||||||
self.assertRaises(AttributeError,
|
|
||||||
- sign_rsa_sha1_with_client,
|
|
||||||
+ sign_rsa_sha256_with_client,
|
|
||||||
self.eg_signature_base_string,
|
|
||||||
self.rsa_public_client) # public key doesn't sign
|
|
||||||
|
|
||||||
@@ -770,11 +771,11 @@ MmgDHR2tt8KeYTSgfU+BAkBcaVF91EQ7VXhvyABNYjeYP7lU7orOgdWMa/zbLXSU
|
|
||||||
|
|
||||||
for bad_value in [None, '', 'foobar', self.rsa_private_client.rsa_key]:
|
|
||||||
self.assertRaises(TypeError,
|
|
||||||
- verify_rsa_sha1,
|
|
||||||
+ verify_rsa_sha256,
|
|
||||||
MockRequest('POST',
|
|
||||||
'http://example.com/request',
|
|
||||||
self.eg_params,
|
|
||||||
- self.expected_signature_rsa_sha1),
|
|
||||||
+ self.expected_signature_rsa_sha256),
|
|
||||||
MockClient(rsa_key=bad_value))
|
|
||||||
|
|
||||||
# For completeness, this text could repeat the above for RSA-SHA256 and
|
|
||||||
--
|
|
||||||
2.26.3
|
|
||||||
|
|
@ -1,328 +0,0 @@
|
|||||||
diff -up oauthlib-3.1.1/oauthlib/oauth1/__init__.py.orig oauthlib-3.1.1/oauthlib/oauth1/__init__.py
|
|
||||||
--- oauthlib-3.1.1/oauthlib/oauth1/__init__.py.orig 2022-07-12 14:00:51.468041694 +0200
|
|
||||||
+++ oauthlib-3.1.1/oauthlib/oauth1/__init__.py 2022-07-12 14:02:06.102946935 +0200
|
|
||||||
@@ -10,8 +10,6 @@ from .rfc5849 import (SIGNATURE_HMAC,
|
|
||||||
SIGNATURE_HMAC_SHA1,
|
|
||||||
SIGNATURE_HMAC_SHA256,
|
|
||||||
SIGNATURE_HMAC_SHA512,
|
|
||||||
- SIGNATURE_RSA_SHA256,
|
|
||||||
- SIGNATURE_RSA_SHA512,
|
|
||||||
SIGNATURE_PLAINTEXT)
|
|
||||||
from .rfc5849 import SIGNATURE_TYPE_AUTH_HEADER, SIGNATURE_TYPE_QUERY
|
|
||||||
from .rfc5849 import SIGNATURE_TYPE_BODY
|
|
||||||
diff -up oauthlib-3.1.1/oauthlib/oauth1/rfc5849/endpoints/base.py.orig oauthlib-3.1.1/oauthlib/oauth1/rfc5849/endpoints/base.py
|
|
||||||
--- oauthlib-3.1.1/oauthlib/oauth1/rfc5849/endpoints/base.py.orig 2022-07-13 16:45:37.104370084 +0200
|
|
||||||
+++ oauthlib-3.1.1/oauthlib/oauth1/rfc5849/endpoints/base.py 2022-07-12 14:17:46.689355274 +0200
|
|
||||||
@@ -180,27 +180,11 @@ class BaseEndpoint:
|
|
||||||
description='Invalid nonce format.')
|
|
||||||
|
|
||||||
def _check_signature(self, request, is_token_request=False):
|
|
||||||
- # ---- RSA-SHA1 is not allowed ------
|
|
||||||
- if request.signature_method == SIGNATURE_RSA_SHA1:
|
|
||||||
- raise ValueError("Using RSA-SHA1 is deprecated, use HMAC-SHA1 or a stronger RSA-SHA***")
|
|
||||||
-
|
|
||||||
- # ---- RSA Signature verification ----
|
|
||||||
- if request.signature_method == SIGNATURE_RSA_SHA256 or \
|
|
||||||
- request.signature_method == SIGNATURE_RSA_SHA512:
|
|
||||||
- # RSA-based signature method
|
|
||||||
-
|
|
||||||
- # The server verifies the signature per `[RFC3447] section 8.2.2`_
|
|
||||||
- # .. _`[RFC3447] section 8.2.2`: https://tools.ietf.org/html/rfc3447#section-8.2.1
|
|
||||||
-
|
|
||||||
- rsa_key = self.request_validator.get_rsa_key(
|
|
||||||
- request.client_key, request)
|
|
||||||
-
|
|
||||||
- if request.signature_method == SIGNATURE_RSA_SHA256:
|
|
||||||
- valid_signature = signature.verify_rsa_sha256(request, rsa_key)
|
|
||||||
- elif request.signature_method == SIGNATURE_RSA_SHA512:
|
|
||||||
- valid_signature = signature.verify_rsa_sha512(request, rsa_key)
|
|
||||||
- else:
|
|
||||||
- valid_signature = False
|
|
||||||
+ # ---- RSA-SHA is not allowed ------
|
|
||||||
+ if request.signature_method in (SIGNATURE_RSA_SHA1,
|
|
||||||
+ SIGNATURE_RSA_SHA256,
|
|
||||||
+ SIGNATURE_RSA_SHA512):
|
|
||||||
+ raise ValueError("Using RSA-SHA is deprecated, use HMAC-SHA")
|
|
||||||
|
|
||||||
# ---- HMAC or Plaintext Signature verification ----
|
|
||||||
else:
|
|
||||||
diff -up oauthlib-3.1.1/oauthlib/oauth1/rfc5849/__init__.py.orig oauthlib-3.1.1/oauthlib/oauth1/rfc5849/__init__.py
|
|
||||||
--- oauthlib-3.1.1/oauthlib/oauth1/rfc5849/__init__.py.orig 2022-07-13 16:45:37.103370073 +0200
|
|
||||||
+++ oauthlib-3.1.1/oauthlib/oauth1/rfc5849/__init__.py 2022-07-12 14:05:31.087433182 +0200
|
|
||||||
@@ -78,7 +78,7 @@ class Client:
|
|
||||||
SIGNATURE_HMAC_SHA1: signature.sign_hmac_sha1_with_client,
|
|
||||||
SIGNATURE_HMAC_SHA256: signature.sign_hmac_sha256_with_client,
|
|
||||||
SIGNATURE_HMAC_SHA512: signature.sign_hmac_sha512_with_client,
|
|
||||||
- # sign_rsa_sha1_with_client actually points out to a dummy method
|
|
||||||
+ # sign_rsa_shaXYZ_with_client actually points out to a dummy method
|
|
||||||
# that just throws an exception
|
|
||||||
SIGNATURE_RSA_SHA1: signature.sign_rsa_sha1_with_client,
|
|
||||||
SIGNATURE_RSA_SHA256: signature.sign_rsa_sha256_with_client,
|
|
||||||
diff -up oauthlib-3.1.1/oauthlib/oauth1/rfc5849/signature.py.orig oauthlib-3.1.1/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
--- oauthlib-3.1.1/oauthlib/oauth1/rfc5849/signature.py.orig 2022-07-13 16:45:37.104370084 +0200
|
|
||||||
+++ oauthlib-3.1.1/oauthlib/oauth1/rfc5849/signature.py 2022-08-10 12:05:45.642421443 +0200
|
|
||||||
@@ -559,16 +559,17 @@ def _get_jwt_rsa_algorithm(hash_algorith
|
|
||||||
# Not in cache: instantiate a new RSAAlgorithm
|
|
||||||
|
|
||||||
# PyJWT has some nice pycrypto/cryptography abstractions
|
|
||||||
- import jwt.algorithms as jwt_algorithms
|
|
||||||
- m = {
|
|
||||||
- 'SHA-256': jwt_algorithms.hashes.SHA256,
|
|
||||||
- 'SHA-512': jwt_algorithms.hashes.SHA512,
|
|
||||||
- }
|
|
||||||
- v = jwt_algorithms.RSAAlgorithm(m[hash_algorithm_name])
|
|
||||||
+ # import jwt.algorithms as jwt_algorithms
|
|
||||||
+ #m = {
|
|
||||||
+ # 'SHA-256': jwt_algorithms.hashes.SHA256,
|
|
||||||
+ # 'SHA-512': jwt_algorithms.hashes.SHA512,
|
|
||||||
+ #}
|
|
||||||
+ #v = jwt_algorithms.RSAAlgorithm(m[hash_algorithm_name])
|
|
||||||
|
|
||||||
- _jwt_rsa[hash_algorithm_name] = v # populate cache
|
|
||||||
+ #_jwt_rsa[hash_algorithm_name] = v # populate cache
|
|
||||||
|
|
||||||
- return v
|
|
||||||
+ #return v
|
|
||||||
+ return None
|
|
||||||
|
|
||||||
|
|
||||||
def _prepare_key_plus(alg, keystr):
|
|
||||||
@@ -612,6 +613,7 @@ def _sign_rsa(hash_algorithm_name: str,
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Get the implementation of RSA-hash
|
|
||||||
+ raise ValueError('Invalid signature method.')
|
|
||||||
|
|
||||||
alg = _get_jwt_rsa_algorithm(hash_algorithm_name)
|
|
||||||
|
|
||||||
diff -up oauthlib-3.1.1/tests/oauth1/rfc5849/test_client.py.orig oauthlib-3.1.1/tests/oauth1/rfc5849/test_client.py
|
|
||||||
--- oauthlib-3.1.1/tests/oauth1/rfc5849/test_client.py.orig 2022-07-13 16:45:37.104370084 +0200
|
|
||||||
+++ oauthlib-3.1.1/tests/oauth1/rfc5849/test_client.py 2022-08-09 11:46:07.105962442 +0200
|
|
||||||
@@ -2,7 +2,7 @@
|
|
||||||
from oauthlib.common import Request
|
|
||||||
from oauthlib.oauth1 import (
|
|
||||||
SIGNATURE_HMAC_SHA1, SIGNATURE_HMAC_SHA256, SIGNATURE_PLAINTEXT,
|
|
||||||
- SIGNATURE_RSA_SHA256, SIGNATURE_TYPE_BODY, SIGNATURE_TYPE_QUERY,
|
|
||||||
+ SIGNATURE_TYPE_BODY, SIGNATURE_TYPE_QUERY,
|
|
||||||
)
|
|
||||||
from oauthlib.oauth1.rfc5849 import Client
|
|
||||||
|
|
||||||
@@ -74,14 +74,6 @@ class ClientConstructorTests(TestCase):
|
|
||||||
self.assertEqual(Client.SIGNATURE_METHODS[SIGNATURE_HMAC_SHA256],
|
|
||||||
client.SIGNATURE_METHODS[client.signature_method])
|
|
||||||
|
|
||||||
- def test_rsa(self):
|
|
||||||
- client = Client('client_key', signature_method=SIGNATURE_RSA_SHA256)
|
|
||||||
- # instance is using the correct signer method
|
|
||||||
- self.assertEqual(Client.SIGNATURE_METHODS[SIGNATURE_RSA_SHA256],
|
|
||||||
- client.SIGNATURE_METHODS[client.signature_method])
|
|
||||||
- # don't need an RSA key to instantiate
|
|
||||||
- self.assertIsNone(client.rsa_key)
|
|
||||||
-
|
|
||||||
|
|
||||||
class SignatureMethodTest(TestCase):
|
|
||||||
|
|
||||||
@@ -104,35 +96,6 @@ class SignatureMethodTest(TestCase):
|
|
||||||
'oauth_signature="JzgJWBxX664OiMW3WE4MEjtYwOjI%2FpaUWHqtdHe68Es%3D"')
|
|
||||||
self.assertEqual(h['Authorization'], correct)
|
|
||||||
|
|
||||||
- def test_rsa_method(self):
|
|
||||||
- private_key = (
|
|
||||||
- "-----BEGIN RSA PRIVATE KEY-----\nMIICXgIBAAKBgQDk1/bxy"
|
|
||||||
- "S8Q8jiheHeYYp/4rEKJopeQRRKKpZI4s5i+UPwVpupG\nAlwXWfzXw"
|
|
||||||
- "SMaKPAoKJNdu7tqKRniqst5uoHXw98gj0x7zamu0Ck1LtQ4c7pFMVa"
|
|
||||||
- "h\n5IYGhBi2E9ycNS329W27nJPWNCbESTu7snVlG8V8mfvGGg3xNjT"
|
|
||||||
- "MO7IdrwIDAQAB\nAoGBAOQ2KuH8S5+OrsL4K+wfjoCi6MfxCUyqVU9"
|
|
||||||
- "GxocdM1m30WyWRFMEz2nKJ8fR\np3vTD4w8yplTOhcoXdQZl0kRoaD"
|
|
||||||
- "zrcYkm2VvJtQRrX7dKFT8dR8D/Tr7dNQLOXfC\nDY6xveQczE7qt7V"
|
|
||||||
- "k7lp4FqmxBsaaEuokt78pOOjywZoInjZhAkEA9wz3zoZNT0/i\nrf6"
|
|
||||||
- "qv2qTIeieUB035N3dyw6f1BGSWYaXSuerDCD/J1qZbAPKKhyHZbVaw"
|
|
||||||
- "Ft3UMhe\n542UftBaxQJBAO0iJy1I8GQjGnS7B3yvyH3CcLYGy296+"
|
|
||||||
- "XO/2xKp/d/ty1OIeovx\nC60pLNwuFNF3z9d2GVQAdoQ89hUkOtjZL"
|
|
||||||
- "eMCQQD0JO6oPHUeUjYT+T7ImAv7UKVT\nSuy30sKjLzqoGw1kR+wv7"
|
|
||||||
- "C5PeDRvscs4wa4CW9s6mjSrMDkDrmCLuJDtmf55AkEA\nkmaMg2PNr"
|
|
||||||
- "jUR51F0zOEFycaaqXbGcFwe1/xx9zLmHzMDXd4bsnwt9kk+fe0hQzV"
|
|
||||||
- "S\nJzatanQit3+feev1PN3QewJAWv4RZeavEUhKv+kLe95Yd0su7lT"
|
|
||||||
- "LVduVgh4v5yLT\nGa6FHdjGPcfajt+nrpB1n8UQBEH9ZxniokR/IPv"
|
|
||||||
- "dMlxqXA==\n-----END RSA PRIVATE KEY-----"
|
|
||||||
- )
|
|
||||||
- client = Client('client_key', signature_method=SIGNATURE_RSA_SHA256,
|
|
||||||
- rsa_key=private_key, timestamp='1234567890', nonce='abc')
|
|
||||||
- u, h, b = client.sign('http://example.com')
|
|
||||||
- correct = ('OAuth oauth_nonce="abc", oauth_timestamp="1234567890", '
|
|
||||||
- 'oauth_version="1.0", oauth_signature_method="RSA-SHA256", '
|
|
||||||
- 'oauth_consumer_key="client_key", '
|
|
||||||
- 'oauth_signature="hJE2IGqCn3bw7ecu6psnsImrvERhTd667aIENzWbzdRGxEWwvAwJvWWCffD8P0Ox9IEu3gKD%2FzYdr36tBhW%2FMvdFsOAr4F41ojznv1urY6%2FD9FRs1py9dYuj1vdFYFUzziMBDv2w2emidDk8PqfHT1we5%2FIcH%2FKNCjMbkQgxsqE%3D"')
|
|
||||||
- self.assertEqual(h['Authorization'], correct)
|
|
||||||
-
|
|
||||||
def test_plaintext_method(self):
|
|
||||||
client = Client('client_key',
|
|
||||||
signature_method=SIGNATURE_PLAINTEXT,
|
|
||||||
@@ -151,10 +114,6 @@ class SignatureMethodTest(TestCase):
|
|
||||||
client = Client('client_key', signature_method='invalid')
|
|
||||||
self.assertRaises(ValueError, client.sign, 'http://example.com')
|
|
||||||
|
|
||||||
- def test_rsa_no_key(self):
|
|
||||||
- client = Client('client_key', signature_method=SIGNATURE_RSA_SHA256)
|
|
||||||
- self.assertRaises(ValueError, client.sign, 'http://example.com')
|
|
||||||
-
|
|
||||||
def test_register_method(self):
|
|
||||||
Client.register_signature_method('PIZZA',
|
|
||||||
lambda base_string, client: 'PIZZA')
|
|
||||||
diff -up oauthlib-3.1.1/tests/oauth1/rfc5849/test_signatures.py.orig oauthlib-3.1.1/tests/oauth1/rfc5849/test_signatures.py
|
|
||||||
--- oauthlib-3.1.1/tests/oauth1/rfc5849/test_signatures.py.orig 2022-07-13 16:45:37.104370084 +0200
|
|
||||||
+++ oauthlib-3.1.1/tests/oauth1/rfc5849/test_signatures.py 2022-08-09 11:55:56.834032943 +0200
|
|
||||||
@@ -657,129 +657,38 @@ GLYT3Jw1Lfb1bbuck9Y0JsRJO7uydWUbxXyZ+8Ya
|
|
||||||
|
|
||||||
def test_sign_rsa_sha256_with_client(self):
|
|
||||||
"""
|
|
||||||
- Test sign and verify with RSA-SHA256.
|
|
||||||
- """
|
|
||||||
- self.assertEqual(
|
|
||||||
- self.expected_signature_rsa_sha256,
|
|
||||||
- sign_rsa_sha256_with_client(self.eg_signature_base_string,
|
|
||||||
- self.rsa_private_client))
|
|
||||||
- self.assertTrue(verify_rsa_sha256(
|
|
||||||
- MockRequest('POST',
|
|
||||||
- 'http://example.com/request',
|
|
||||||
- self.eg_params,
|
|
||||||
- self.expected_signature_rsa_sha256),
|
|
||||||
- self.rsa_public_client.rsa_key))
|
|
||||||
-
|
|
||||||
- def test_sign_rsa_sha512_with_client(self):
|
|
||||||
- """
|
|
||||||
- Test sign and verify with RSA-SHA512.
|
|
||||||
- """
|
|
||||||
- self.assertEqual(
|
|
||||||
- self.expected_signature_rsa_sha512,
|
|
||||||
- sign_rsa_sha512_with_client(self.eg_signature_base_string,
|
|
||||||
- self.rsa_private_client))
|
|
||||||
- self.assertTrue(verify_rsa_sha512(
|
|
||||||
- MockRequest('POST',
|
|
||||||
- 'http://example.com/request',
|
|
||||||
- self.eg_params,
|
|
||||||
- self.expected_signature_rsa_sha512),
|
|
||||||
- self.rsa_public_client.rsa_key))
|
|
||||||
-
|
|
||||||
- def test_rsa_false_positives(self):
|
|
||||||
- """
|
|
||||||
- Test verify_rsa-* functions will correctly detect invalid signatures.
|
|
||||||
+ Test sign and verify with RSA-SHA256 throws an exception.
|
|
||||||
"""
|
|
||||||
+ self.assertRaises(ValueError,
|
|
||||||
+ sign_rsa_sha256_with_client,
|
|
||||||
+ self.eg_signature_base_string,
|
|
||||||
+ self.rsa_private_client)
|
|
||||||
|
|
||||||
- another_client = MockClient(rsa_key='''
|
|
||||||
------BEGIN RSA PRIVATE KEY-----
|
|
||||||
-MIICXQIBAAKBgQDZcD/1OZNJJ6Y3QZM16Z+O7fkD9kTIQuT2BfpAOUvDfxzYhVC9
|
|
||||||
-TNmSDHCQhr+ClutyolBk5jTE1/FXFUuHoPsTrkI7KQFXPP834D4gnSY9jrAiUJHe
|
|
||||||
-DVF6wXNuS7H4Ueh16YPjUxgLLRh/nn/JSEj98gsw+7DP01OWMfWS99S7eQIDAQAB
|
|
||||||
-AoGBALsQZRXVyK7BG7CiC8HwEcNnXDpaXmZjlpNKJTenk1THQMvONd4GBZAuf5D3
|
|
||||||
-PD9fE4R1u/ByVKecmBaxTV+L0TRQfD8K/nbQe0SKRQIkLI2ymLJKC/eyw5iTKT0E
|
|
||||||
-+BS6wYpVd+mfcqgvpHOYpUmz9X8k/eOa7uslFmvt+sDb5ZcBAkEA+++SRqqUxFEG
|
|
||||||
-s/ZWAKw9p5YgkeVUOYVUwyAeZ97heySrjVzg1nZ6v6kv7iOPi9KOEpaIGPW7x1K/
|
|
||||||
-uQuSt4YEqQJBANzyNqZTTPpv7b/R8ABFy0YMwPVNt3b1GOU1Xxl6iuhH2WcHuueo
|
|
||||||
-UB13JHoZCMZ7hsEqieEz6uteUjdRzRPKclECQFNhVK4iop3emzNQYeJTHwyp+RmQ
|
|
||||||
-JrHq2MTDioyiDUouNsDQbnFMQQ/RtNVB265Q/0hTnbN1ELLFRkK9+87VghECQQC9
|
|
||||||
-hacLFPk6+TffCp3sHfI3rEj4Iin1iFhKhHWGzW7JwJfjoOXaQK44GDLZ6Q918g+t
|
|
||||||
-MmgDHR2tt8KeYTSgfU+BAkBcaVF91EQ7VXhvyABNYjeYP7lU7orOgdWMa/zbLXSU
|
|
||||||
-4vLsK1WOmwPY9zsXpPkilqszqcru4gzlG462cSbEdAW9
|
|
||||||
------END RSA PRIVATE KEY-----
|
|
||||||
-''')
|
|
||||||
-
|
|
||||||
- for functions in [
|
|
||||||
- (sign_rsa_sha256_with_client, verify_rsa_sha256),
|
|
||||||
- (sign_rsa_sha512_with_client, verify_rsa_sha512),
|
|
||||||
- ]:
|
|
||||||
- signing_function = functions[0]
|
|
||||||
- verify_function = functions[1]
|
|
||||||
-
|
|
||||||
- good_signature = \
|
|
||||||
- signing_function(self.eg_signature_base_string,
|
|
||||||
- self.rsa_private_client)
|
|
||||||
-
|
|
||||||
- bad_signature_on_different_value = \
|
|
||||||
- signing_function('wrong value signed', self.rsa_private_client)
|
|
||||||
-
|
|
||||||
- bad_signature_produced_by_different_private_key = \
|
|
||||||
- signing_function(self.eg_signature_base_string, another_client)
|
|
||||||
-
|
|
||||||
- self.assertTrue(verify_function(
|
|
||||||
- MockRequest('POST',
|
|
||||||
- 'http://example.com/request',
|
|
||||||
- self.eg_params,
|
|
||||||
- good_signature),
|
|
||||||
- self.rsa_public_client.rsa_key))
|
|
||||||
-
|
|
||||||
- for bad_signature in [
|
|
||||||
- '',
|
|
||||||
- 'ZG9uJ3QgdHJ1c3QgbWUK', # random base64 encoded value
|
|
||||||
- 'altérer', # value with a non-ASCII character in it
|
|
||||||
- bad_signature_on_different_value,
|
|
||||||
- bad_signature_produced_by_different_private_key,
|
|
||||||
- ]:
|
|
||||||
- self.assertFalse(verify_function(
|
|
||||||
- MockRequest('POST',
|
|
||||||
- 'http://example.com/request',
|
|
||||||
- self.eg_params,
|
|
||||||
- bad_signature),
|
|
||||||
- self.rsa_public_client.rsa_key))
|
|
||||||
+ self.assertRaises(ValueError,
|
|
||||||
+ verify_rsa_sha1,
|
|
||||||
+ MockRequest('POST',
|
|
||||||
+ 'http://example.com/request',
|
|
||||||
+ self.eg_params,
|
|
||||||
+ self.expected_signature_rsa_sha256),
|
|
||||||
+ self.rsa_public_client.rsa_key)
|
|
||||||
|
|
||||||
- def test_rsa_bad_keys(self):
|
|
||||||
+ def test_sign_rsa_sha512_with_client(self):
|
|
||||||
"""
|
|
||||||
- Testing RSA sign and verify with bad key values produces errors.
|
|
||||||
-
|
|
||||||
- This test is useful for coverage tests, since it runs the code branches
|
|
||||||
- that deal with error situations.
|
|
||||||
+ Test sign and verify with RSA-SHA512 throws an exception.
|
|
||||||
"""
|
|
||||||
-
|
|
||||||
- # Signing needs a private key
|
|
||||||
-
|
|
||||||
- for bad_value in [None, '', 'foobar']:
|
|
||||||
- self.assertRaises(ValueError,
|
|
||||||
- sign_rsa_sha256_with_client,
|
|
||||||
- self.eg_signature_base_string,
|
|
||||||
- MockClient(rsa_key=bad_value))
|
|
||||||
-
|
|
||||||
- self.assertRaises(AttributeError,
|
|
||||||
- sign_rsa_sha256_with_client,
|
|
||||||
+ self.assertRaises(ValueError,
|
|
||||||
+ sign_rsa_sha512_with_client,
|
|
||||||
self.eg_signature_base_string,
|
|
||||||
- self.rsa_public_client) # public key doesn't sign
|
|
||||||
-
|
|
||||||
- # Verify needs a public key
|
|
||||||
+ self.rsa_private_client)
|
|
||||||
|
|
||||||
- for bad_value in [None, '', 'foobar', self.rsa_private_client.rsa_key]:
|
|
||||||
- self.assertRaises(TypeError,
|
|
||||||
- verify_rsa_sha256,
|
|
||||||
- MockRequest('POST',
|
|
||||||
- 'http://example.com/request',
|
|
||||||
- self.eg_params,
|
|
||||||
- self.expected_signature_rsa_sha256),
|
|
||||||
- MockClient(rsa_key=bad_value))
|
|
||||||
+ self.assertRaises(ValueError,
|
|
||||||
+ verify_rsa_sha1,
|
|
||||||
+ MockRequest('POST',
|
|
||||||
+ 'http://example.com/request',
|
|
||||||
+ self.eg_params,
|
|
||||||
+ self.expected_signature_rsa_sha512),
|
|
||||||
+ self.rsa_public_client.rsa_key)
|
|
||||||
|
|
||||||
- # For completeness, this text could repeat the above for RSA-SHA256 and
|
|
||||||
- # RSA-SHA512 signing and verification functions.
|
|
||||||
|
|
||||||
def test_rsa_jwt_algorithm_cache(self):
|
|
||||||
# Tests cache of RSAAlgorithm objects is implemented correctly.
|
|
@ -1,95 +0,0 @@
|
|||||||
diff -up oauthlib-3.1.1/oauthlib/uri_validate.py.orig oauthlib-3.1.1/oauthlib/uri_validate.py
|
|
||||||
--- oauthlib-3.1.1/oauthlib/uri_validate.py.orig 2021-06-01 21:11:24.000000000 +0200
|
|
||||||
+++ oauthlib-3.1.1/oauthlib/uri_validate.py 2022-10-24 14:42:42.147180444 +0200
|
|
||||||
@@ -66,7 +66,7 @@ IPv4address = r"%(dec_octet)s \. %(dec_o
|
|
||||||
)
|
|
||||||
|
|
||||||
# IPv6address
|
|
||||||
-IPv6address = r"([A-Fa-f0-9:]+:+)+[A-Fa-f0-9]+"
|
|
||||||
+IPv6address = r"([A-Fa-f0-9:]+[:$])[A-Fa-f0-9]{1,4}"
|
|
||||||
|
|
||||||
# IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
|
|
||||||
IPvFuture = r"v %(HEXDIG)s+ \. (?: %(unreserved)s | %(sub_delims)s | : )+" % locals()
|
|
||||||
diff -up oauthlib-3.1.1/tests/test_uri_validate.py.orig oauthlib-3.1.1/tests/test_uri_validate.py
|
|
||||||
--- oauthlib-3.1.1/tests/test_uri_validate.py.orig 2021-06-01 21:11:24.000000000 +0200
|
|
||||||
+++ oauthlib-3.1.1/tests/test_uri_validate.py 2022-10-24 14:44:26.180296911 +0200
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-import oauthlib
|
|
||||||
+import unittest
|
|
||||||
from oauthlib.uri_validate import is_absolute_uri
|
|
||||||
|
|
||||||
from tests.unittest import TestCase
|
|
||||||
@@ -7,7 +7,6 @@ from tests.unittest import TestCase
|
|
||||||
class UriValidateTest(TestCase):
|
|
||||||
|
|
||||||
def test_is_absolute_uri(self):
|
|
||||||
-
|
|
||||||
self.assertIsNotNone(is_absolute_uri('schema://example.com/path'))
|
|
||||||
self.assertIsNotNone(is_absolute_uri('https://example.com/path'))
|
|
||||||
self.assertIsNotNone(is_absolute_uri('https://example.com'))
|
|
||||||
@@ -17,17 +16,64 @@ class UriValidateTest(TestCase):
|
|
||||||
self.assertIsNotNone(is_absolute_uri('http://example.com'))
|
|
||||||
self.assertIsNotNone(is_absolute_uri('http://example.com/path'))
|
|
||||||
self.assertIsNotNone(is_absolute_uri('http://example.com:80/path'))
|
|
||||||
- self.assertIsNotNone(is_absolute_uri('com.example.bundle.id:/'))
|
|
||||||
+
|
|
||||||
+ def test_query(self):
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://example.com:80/path?foo'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://example.com:80/path?foo=bar'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://example.com:80/path?foo=bar&fruit=banana'))
|
|
||||||
+
|
|
||||||
+ def test_fragment_forbidden(self):
|
|
||||||
+ self.assertIsNone(is_absolute_uri('http://example.com:80/path#foo'))
|
|
||||||
+ self.assertIsNone(is_absolute_uri('http://example.com:80/path#foo=bar'))
|
|
||||||
+ self.assertIsNone(is_absolute_uri('http://example.com:80/path#foo=bar&fruit=banana'))
|
|
||||||
+
|
|
||||||
+ def test_combined_forbidden(self):
|
|
||||||
+ self.assertIsNone(is_absolute_uri('http://example.com:80/path?foo#bar'))
|
|
||||||
+ self.assertIsNone(is_absolute_uri('http://example.com:80/path?foo&bar#fruit'))
|
|
||||||
+ self.assertIsNone(is_absolute_uri('http://example.com:80/path?foo=1&bar#fruit=banana'))
|
|
||||||
+ self.assertIsNone(is_absolute_uri('http://example.com:80/path?foo=1&bar=2#fruit=banana&bar=foo'))
|
|
||||||
+
|
|
||||||
+ def test_custom_scheme(self):
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('com.example.bundle.id://'))
|
|
||||||
+
|
|
||||||
+ def test_ipv6_bracket(self):
|
|
||||||
self.assertIsNotNone(is_absolute_uri('http://[::1]:38432/path'))
|
|
||||||
self.assertIsNotNone(is_absolute_uri('http://[::1]/path'))
|
|
||||||
self.assertIsNotNone(is_absolute_uri('http://[fd01:0001::1]/path'))
|
|
||||||
self.assertIsNotNone(is_absolute_uri('http://[fd01:1::1]/path'))
|
|
||||||
self.assertIsNotNone(is_absolute_uri('http://[0123:4567:89ab:cdef:0123:4567:89ab:cdef]/path'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://[0123:4567:89ab:cdef:0123:4567:89ab:cdef]:8080/path'))
|
|
||||||
+
|
|
||||||
+ @unittest.skip("ipv6 edge-cases not supported")
|
|
||||||
+ def test_ipv6_edge_cases(self):
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://2001:db8::'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://::1234:5678'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://2001:db8::1234:5678'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://2001:db8:3333:4444:5555:6666:7777:8888'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://2001:db8:3333:4444:CCCC:DDDD:EEEE:FFFF'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://0123:4567:89ab:cdef:0123:4567:89ab:cdef/path'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://::'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://2001:0db8:0001:0000:0000:0ab9:C0A8:0102'))
|
|
||||||
+
|
|
||||||
+ @unittest.skip("ipv6 dual ipv4 not supported")
|
|
||||||
+ def test_ipv6_dual(self):
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://2001:db8:3333:4444:5555:6666:1.2.3.4'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://::11.22.33.44'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://2001:db8::123.123.123.123'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://::1234:5678:91.123.4.56'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://::1234:5678:1.2.3.4'))
|
|
||||||
+ self.assertIsNotNone(is_absolute_uri('http://2001:db8::1234:5678:5.6.7.8'))
|
|
||||||
+
|
|
||||||
+ def test_ipv4(self):
|
|
||||||
self.assertIsNotNone(is_absolute_uri('http://127.0.0.1:38432/'))
|
|
||||||
self.assertIsNotNone(is_absolute_uri('http://127.0.0.1:38432/'))
|
|
||||||
self.assertIsNotNone(is_absolute_uri('http://127.1:38432/'))
|
|
||||||
|
|
||||||
+ def test_failures(self):
|
|
||||||
self.assertIsNone(is_absolute_uri('http://example.com:notaport/path'))
|
|
||||||
self.assertIsNone(is_absolute_uri('wrong'))
|
|
||||||
self.assertIsNone(is_absolute_uri('http://[:1]:38432/path'))
|
|
||||||
self.assertIsNone(is_absolute_uri('http://[abcd:efgh::1]/'))
|
|
||||||
+
|
|
||||||
+ def test_malitious_semicolon(self):
|
|
||||||
+ self.assertIsNone(is_absolute_uri('http://[::::::::::::::::::::::::::]/path'))
|
|
@ -1,240 +0,0 @@
|
|||||||
From 49294a6a7cb6e9ece1c1814d629e2d9e497180fa Mon Sep 17 00:00:00 2001
|
|
||||||
From: Dariusz Smigiel <dsmigiel@redhat.com>
|
|
||||||
Date: Thu, 19 May 2022 09:41:59 -0700
|
|
||||||
Subject: [PATCH 1/4] OAuth1: Allow IPv6 addresses being parsed by signature
|
|
||||||
|
|
||||||
This PR addresses issue with incorrectly parsing IPv6 address,
|
|
||||||
described here: https://github.com/oauthlib/oauthlib/issues/817
|
|
||||||
---
|
|
||||||
oauthlib/oauth1/rfc5849/signature.py | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/oauthlib/oauth1/rfc5849/signature.py b/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
index a370ccd6..424393b6 100644
|
|
||||||
--- a/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
+++ b/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
@@ -173,7 +173,7 @@ def base_string_uri(uri: str, host: str = None) -> str:
|
|
||||||
if ':' in netloc:
|
|
||||||
# Contains a colon ":", so try to parse as "host:port"
|
|
||||||
|
|
||||||
- hostname, port_str = netloc.split(':', 1)
|
|
||||||
+ hostname, port_str = netloc.rsplit(':', 1)
|
|
||||||
|
|
||||||
if len(hostname) == 0:
|
|
||||||
raise ValueError('missing host') # error: netloc was ":port" or ":"
|
|
||||||
|
|
||||||
From d05c388078b45285ac4a012c568a5e2d56556a34 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Dariusz Smigiel <dsmigiel@redhat.com>
|
|
||||||
Date: Wed, 15 Jun 2022 09:26:20 -0700
|
|
||||||
Subject: [PATCH 2/4] Removed dependency on split
|
|
||||||
|
|
||||||
---
|
|
||||||
oauthlib/oauth1/rfc5849/signature.py | 68 +++++++++++++++----------
|
|
||||||
tests/oauth1/rfc5849/test_signatures.py | 21 +++++++-
|
|
||||||
2 files changed, 60 insertions(+), 29 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/oauthlib/oauth1/rfc5849/signature.py b/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
index 424393b6..70447852 100644
|
|
||||||
--- a/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
+++ b/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
@@ -37,6 +37,7 @@
|
|
||||||
import binascii
|
|
||||||
import hashlib
|
|
||||||
import hmac
|
|
||||||
+import ipaddress
|
|
||||||
import logging
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
@@ -131,7 +132,14 @@ def base_string_uri(uri: str, host: str = None) -> str:
|
|
||||||
raise ValueError('uri must be a string.')
|
|
||||||
|
|
||||||
# FIXME: urlparse does not support unicode
|
|
||||||
- scheme, netloc, path, params, query, fragment = urlparse.urlparse(uri)
|
|
||||||
+ output = urlparse.urlparse(uri)
|
|
||||||
+ scheme = output.scheme
|
|
||||||
+ hostname = output.hostname
|
|
||||||
+ port = output.port
|
|
||||||
+ path = output.path
|
|
||||||
+ params = output.params
|
|
||||||
+ query = output.query
|
|
||||||
+ fragment = output.fragment
|
|
||||||
|
|
||||||
# The scheme, authority, and path of the request resource URI `RFC3986`
|
|
||||||
# are included by constructing an "http" or "https" URI representing
|
|
||||||
@@ -153,13 +161,22 @@ def base_string_uri(uri: str, host: str = None) -> str:
|
|
||||||
|
|
||||||
# 1. The scheme and host MUST be in lowercase.
|
|
||||||
scheme = scheme.lower()
|
|
||||||
- netloc = netloc.lower()
|
|
||||||
# Note: if ``host`` is used, it will be converted to lowercase below
|
|
||||||
+ if hostname is not None:
|
|
||||||
+ hostname = hostname.lower()
|
|
||||||
|
|
||||||
# 2. The host and port values MUST match the content of the HTTP
|
|
||||||
# request "Host" header field.
|
|
||||||
if host is not None:
|
|
||||||
- netloc = host.lower() # override value in uri with provided host
|
|
||||||
+ # NOTE: override value in uri with provided host
|
|
||||||
+ # Host argument is equal to netloc. It means it's missing scheme.
|
|
||||||
+ # Add it back, before parsing.
|
|
||||||
+
|
|
||||||
+ host = host.lower()
|
|
||||||
+ host = f"{scheme}://{host}"
|
|
||||||
+ output = urlparse.urlparse(host)
|
|
||||||
+ hostname = output.hostname
|
|
||||||
+ port = output.port
|
|
||||||
|
|
||||||
# 3. The port MUST be included if it is not the default port for the
|
|
||||||
# scheme, and MUST be excluded if it is the default. Specifically,
|
|
||||||
@@ -170,33 +187,28 @@ def base_string_uri(uri: str, host: str = None) -> str:
|
|
||||||
# .. _`RFC2616`: https://tools.ietf.org/html/rfc2616
|
|
||||||
# .. _`RFC2818`: https://tools.ietf.org/html/rfc2818
|
|
||||||
|
|
||||||
- if ':' in netloc:
|
|
||||||
- # Contains a colon ":", so try to parse as "host:port"
|
|
||||||
-
|
|
||||||
- hostname, port_str = netloc.rsplit(':', 1)
|
|
||||||
-
|
|
||||||
- if len(hostname) == 0:
|
|
||||||
- raise ValueError('missing host') # error: netloc was ":port" or ":"
|
|
||||||
+ if hostname is None:
|
|
||||||
+ raise ValueError('missing host')
|
|
||||||
|
|
||||||
- if len(port_str) == 0:
|
|
||||||
- netloc = hostname # was "host:", so just use the host part
|
|
||||||
- else:
|
|
||||||
- try:
|
|
||||||
- port_num = int(port_str) # try to parse into an integer number
|
|
||||||
- except ValueError:
|
|
||||||
- raise ValueError('port is not an integer')
|
|
||||||
-
|
|
||||||
- if port_num <= 0 or 65535 < port_num:
|
|
||||||
- raise ValueError('port out of range') # 16-bit unsigned ints
|
|
||||||
- if (scheme, port_num) in (('http', 80), ('https', 443)):
|
|
||||||
- netloc = hostname # default port for scheme: exclude port num
|
|
||||||
- else:
|
|
||||||
- netloc = hostname + ':' + str(port_num) # use hostname:port
|
|
||||||
+ # NOTE: Try guessing if we're dealing with IP or hostname
|
|
||||||
+ try:
|
|
||||||
+ hostname = ipaddress.ip_address(hostname)
|
|
||||||
+ except ValueError:
|
|
||||||
+ pass
|
|
||||||
+
|
|
||||||
+ if isinstance(hostname, ipaddress.IPv6Address):
|
|
||||||
+ hostname = f"[{hostname}]"
|
|
||||||
+ elif isinstance(hostname, ipaddress.IPv4Address):
|
|
||||||
+ hostname = f"{hostname}"
|
|
||||||
+
|
|
||||||
+ if port is not None and not (0 <= port <= 65535):
|
|
||||||
+ raise ValueError('port out of range') # 16-bit unsigned ints
|
|
||||||
+ if (scheme, port) in (('http', 80), ('https', 443)):
|
|
||||||
+ netloc = hostname # default port for scheme: exclude port num
|
|
||||||
+ elif port:
|
|
||||||
+ netloc = f"{hostname}:{port}" # use hostname:port
|
|
||||||
else:
|
|
||||||
- # Does not contain a colon, so entire value must be the hostname
|
|
||||||
-
|
|
||||||
- if len(netloc) == 0:
|
|
||||||
- raise ValueError('missing host') # error: netloc was empty string
|
|
||||||
+ netloc = hostname
|
|
||||||
|
|
||||||
v = urlparse.urlunparse((scheme, netloc, path, params, '', ''))
|
|
||||||
|
|
||||||
diff --git a/tests/oauth1/rfc5849/test_signatures.py b/tests/oauth1/rfc5849/test_signatures.py
|
|
||||||
index 3e84f24b..e737e68b 100644
|
|
||||||
--- a/tests/oauth1/rfc5849/test_signatures.py
|
|
||||||
+++ b/tests/oauth1/rfc5849/test_signatures.py
|
|
||||||
@@ -239,6 +239,26 @@ def test_base_string_uri(self):
|
|
||||||
'http://override.example.com/path',
|
|
||||||
base_string_uri('http:///path', 'OVERRIDE.example.com'))
|
|
||||||
|
|
||||||
+ # ----------------
|
|
||||||
+ # Host: valid host allows for IPv4 and IPv6
|
|
||||||
+
|
|
||||||
+ self.assertEqual(
|
|
||||||
+ 'https://192.168.0.1/',
|
|
||||||
+ base_string_uri('https://192.168.0.1')
|
|
||||||
+ )
|
|
||||||
+ self.assertEqual(
|
|
||||||
+ 'https://192.168.0.1:13000/',
|
|
||||||
+ base_string_uri('https://192.168.0.1:13000')
|
|
||||||
+ )
|
|
||||||
+ self.assertEqual(
|
|
||||||
+ 'https://[123:db8:fd00:1000::5]:13000/',
|
|
||||||
+ base_string_uri('https://[123:db8:fd00:1000::5]:13000')
|
|
||||||
+ )
|
|
||||||
+ self.assertEqual(
|
|
||||||
+ 'https://[123:db8:fd00:1000::5]/',
|
|
||||||
+ base_string_uri('https://[123:db8:fd00:1000::5]')
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
# ----------------
|
|
||||||
# Port: default ports always excluded; non-default ports always included
|
|
||||||
|
|
||||||
@@ -339,7 +359,6 @@ def test_base_string_uri(self):
|
|
||||||
self.assertRaises(ValueError, base_string_uri, 'http://:8080')
|
|
||||||
|
|
||||||
# Port is not a valid TCP/IP port number
|
|
||||||
- self.assertRaises(ValueError, base_string_uri, 'http://eg.com:0')
|
|
||||||
self.assertRaises(ValueError, base_string_uri, 'http://eg.com:-1')
|
|
||||||
self.assertRaises(ValueError, base_string_uri, 'http://eg.com:65536')
|
|
||||||
self.assertRaises(ValueError, base_string_uri, 'http://eg.com:3.14')
|
|
||||||
|
|
||||||
From ed0cb63945c4a5940b185823809693b7f97989ad Mon Sep 17 00:00:00 2001
|
|
||||||
From: Dariusz Smigiel <dsmigiel@redhat.com>
|
|
||||||
Date: Wed, 15 Jun 2022 10:20:29 -0700
|
|
||||||
Subject: [PATCH 3/4] Removed unused query and fragment
|
|
||||||
|
|
||||||
---
|
|
||||||
oauthlib/oauth1/rfc5849/signature.py | 2 --
|
|
||||||
1 file changed, 2 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/oauthlib/oauth1/rfc5849/signature.py b/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
index 70447852..7e8044a9 100644
|
|
||||||
--- a/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
+++ b/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
@@ -138,8 +138,6 @@ def base_string_uri(uri: str, host: str = None) -> str:
|
|
||||||
port = output.port
|
|
||||||
path = output.path
|
|
||||||
params = output.params
|
|
||||||
- query = output.query
|
|
||||||
- fragment = output.fragment
|
|
||||||
|
|
||||||
# The scheme, authority, and path of the request resource URI `RFC3986`
|
|
||||||
# are included by constructing an "http" or "https" URI representing
|
|
||||||
|
|
||||||
From 9aa45aaff0cdeab258d18c025cf66e9bdba529c0 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Dariusz Smigiel <dsmigiel@redhat.com>
|
|
||||||
Date: Mon, 27 Jun 2022 07:20:06 -0700
|
|
||||||
Subject: [PATCH 4/4] Restored test for port 0.
|
|
||||||
|
|
||||||
---
|
|
||||||
oauthlib/oauth1/rfc5849/signature.py | 2 +-
|
|
||||||
tests/oauth1/rfc5849/test_signatures.py | 1 +
|
|
||||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/oauthlib/oauth1/rfc5849/signature.py b/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
index 862c3f3c..9cb1a517 100644
|
|
||||||
--- a/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
+++ b/oauthlib/oauth1/rfc5849/signature.py
|
|
||||||
@@ -198,7 +198,7 @@ def base_string_uri(uri: str, host: str = None) -> str:
|
|
||||||
elif isinstance(hostname, ipaddress.IPv4Address):
|
|
||||||
hostname = f"{hostname}"
|
|
||||||
|
|
||||||
- if port is not None and not (0 <= port <= 65535):
|
|
||||||
+ if port is not None and not (0 < port <= 65535):
|
|
||||||
raise ValueError('port out of range') # 16-bit unsigned ints
|
|
||||||
if (scheme, port) in (('http', 80), ('https', 443)):
|
|
||||||
netloc = hostname # default port for scheme: exclude port num
|
|
||||||
diff --git a/tests/oauth1/rfc5849/test_signatures.py b/tests/oauth1/rfc5849/test_signatures.py
|
|
||||||
index f0e18093..2d4735ea 100644
|
|
||||||
--- a/tests/oauth1/rfc5849/test_signatures.py
|
|
||||||
+++ b/tests/oauth1/rfc5849/test_signatures.py
|
|
||||||
@@ -348,6 +348,7 @@ def test_base_string_uri(self):
|
|
||||||
self.assertRaises(ValueError, base_string_uri, 'http://:8080')
|
|
||||||
|
|
||||||
# Port is not a valid TCP/IP port number
|
|
||||||
+ self.assertRaises(ValueError, base_string_uri, 'http://eg.com:0')
|
|
||||||
self.assertRaises(ValueError, base_string_uri, 'http://eg.com:-1')
|
|
||||||
self.assertRaises(ValueError, base_string_uri, 'http://eg.com:65536')
|
|
||||||
self.assertRaises(ValueError, base_string_uri, 'http://eg.com:3.14')
|
|
@ -1,6 +0,0 @@
|
|||||||
--- !Policy
|
|
||||||
product_versions:
|
|
||||||
- rhel-9
|
|
||||||
decision_context: osci_compose_gate
|
|
||||||
rules:
|
|
||||||
- !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}
|
|
@ -1,18 +1,39 @@
|
|||||||
|
%if (0%{?fedora} > 0 && 0%{?fedora} < 32) || (0%{?rhel} > 0 && 0%{?rhel} <= 7)
|
||||||
|
%bcond_without python2
|
||||||
|
%bcond_without python3
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if 0%{?fedora} || 0%{?rhel} >= 8
|
||||||
|
%bcond_with python2
|
||||||
|
%bcond_without python3
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if 0%{?rhel} && 0%{?rhel} <= 7
|
||||||
|
%{!?__python2: %global __python2 /usr/bin/python2}
|
||||||
|
%{!?python2_sitelib: %global python2_sitelib %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())")}
|
||||||
|
%{!?python2_sitearch: %global python2_sitearch %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))")}
|
||||||
|
%{!?py2_build: %global py2_build %{__python2} setup.py build --executable="%{__python2} -s" %{?*}}
|
||||||
|
%{!?py2_install: %global py2_install %{__python2} setup.py install --skip-build --root %{buildroot} %{?*}}
|
||||||
|
%endif
|
||||||
|
|
||||||
%global modname oauthlib
|
%global modname oauthlib
|
||||||
|
|
||||||
Name: python-oauthlib
|
Name: python-oauthlib
|
||||||
Version: 3.1.1
|
Version: 3.0.2
|
||||||
Release: 5%{?dist}
|
Release: 10%{?dist}
|
||||||
Summary: An implementation of the OAuth request-signing logic
|
Summary: An implementation of the OAuth request-signing logic
|
||||||
|
|
||||||
License: BSD
|
License: BSD
|
||||||
URL: https://github.com/oauthlib/oauthlib
|
URL: https://github.com/oauthlib/oauthlib
|
||||||
|
|
||||||
Source0: https://github.com/oauthlib/oauthlib/archive/v%{version}/%{modname}-%{version}.tar.gz
|
# WARNING: The upstream release URL contains a leading 'v' in the
|
||||||
Patch0001: 0001-Rip-out-RSA-SHA1.patch
|
# tarball name, however the URL downloads a tarball name without the
|
||||||
Patch0002: 0002-Rip-out-the-rest-of-RSA.patch
|
# leading 'v'. The packaging guidelines
|
||||||
Patch0003: 0003-IPV6-regex-redirect_uri.patch
|
# (https://fedoraproject.org/wiki/Packaging:SourceURL#Troublesome_URLs)
|
||||||
Patch0004: 0004-IPV6-parsing-signature.patch
|
# state in this case one should just use the tarball name and document
|
||||||
|
# the reason why the full URL was not used.
|
||||||
|
#Source0: https://github.com/oauthlib/oauthlib/archive/v%{modname}-%{version}.tar.gz
|
||||||
|
Source0: %{modname}-%{version}.tar.gz
|
||||||
|
|
||||||
BuildArch: noarch
|
BuildArch: noarch
|
||||||
|
|
||||||
@ -24,18 +45,53 @@ onto your favourite web framework. If you're a maintainer of such a
|
|||||||
library, write a thin veneer on top of OAuthLib and get OAuth support for
|
library, write a thin veneer on top of OAuthLib and get OAuth support for
|
||||||
very little effort.
|
very little effort.
|
||||||
|
|
||||||
|
%if %{with python2}
|
||||||
|
%package -n python2-oauthlib
|
||||||
|
Summary: An implementation of the OAuth request-signing logic
|
||||||
|
%{?python_provide:%python_provide python2-oauthlib}
|
||||||
|
|
||||||
|
BuildRequires: python2-devel
|
||||||
|
BuildRequires: python2-setuptools
|
||||||
|
|
||||||
|
BuildRequires: python2-nose
|
||||||
|
BuildRequires: python2-mock
|
||||||
|
BuildRequires: python2-blinker
|
||||||
|
|
||||||
|
BuildRequires: python2-jwt >= 1.6.0
|
||||||
|
BuildRequires: python2-cryptography >= 1.4.0
|
||||||
|
|
||||||
|
Requires: python2-jwt >= 1.6.0
|
||||||
|
Requires: python2-cryptography >= 1.4.0
|
||||||
|
|
||||||
|
%description -n python2-oauthlib
|
||||||
|
OAuthLib is a generic utility which implements the logic of OAuth without
|
||||||
|
assuming a specific HTTP request object or web framework. Use it to graft
|
||||||
|
OAuth client support onto your favorite HTTP library, or provider support
|
||||||
|
onto your favourite web framework. If you're a maintainer of such a
|
||||||
|
library, write a thin veneer on top of OAuthLib and get OAuth support for
|
||||||
|
very little effort.
|
||||||
|
|
||||||
|
%endif # with python2
|
||||||
|
|
||||||
|
%if %{with python3}
|
||||||
%package -n python3-oauthlib
|
%package -n python3-oauthlib
|
||||||
Summary: An implementation of the OAuth request-signing logic
|
Summary: An implementation of the OAuth request-signing logic
|
||||||
%{?python_provide:%python_provide python3-oauthlib}
|
%{?python_provide:%python_provide python3-oauthlib}
|
||||||
|
|
||||||
Obsoletes: python3-oauthlib+signedtoken < 3.1.0-2
|
|
||||||
|
|
||||||
BuildRequires: python3-devel
|
BuildRequires: python3-devel
|
||||||
BuildRequires: python3-setuptools
|
BuildRequires: python3-setuptools
|
||||||
|
|
||||||
BuildRequires: python3-pytest
|
BuildRequires: python3-nose
|
||||||
|
BuildRequires: python3-mock
|
||||||
|
BuildRequires: python3-blinker
|
||||||
|
|
||||||
|
BuildRequires: python3-jwt >= 1.6.0
|
||||||
BuildRequires: python3-cryptography >= 1.4.0
|
BuildRequires: python3-cryptography >= 1.4.0
|
||||||
|
|
||||||
|
%{?python_extras_subpkg:Recommends: python3-oauthlib+signedtoken}
|
||||||
|
%{!?python_extras_subpkg:Requires: python3-jwt >= 1.6.0}
|
||||||
|
%{!?python_extras_subpkg:Requires: python3-cryptography >= 1.4.0}
|
||||||
|
|
||||||
%description -n python3-oauthlib
|
%description -n python3-oauthlib
|
||||||
OAuthLib is a generic utility which implements the logic of OAuth without
|
OAuthLib is a generic utility which implements the logic of OAuth without
|
||||||
assuming a specific HTTP request object or web framework. Use it to graft
|
assuming a specific HTTP request object or web framework. Use it to graft
|
||||||
@ -44,8 +100,12 @@ onto your favourite web framework. If you're a maintainer of such a
|
|||||||
library, write a thin veneer on top of OAuthLib and get OAuth support for
|
library, write a thin veneer on top of OAuthLib and get OAuth support for
|
||||||
very little effort.
|
very little effort.
|
||||||
|
|
||||||
|
%{?python_extras_subpkg:%python_extras_subpkg -n python3-oauthlib -i %{python3_sitelib}/%{modname}-%{version}-*.egg-info signedtoken}
|
||||||
|
|
||||||
|
%endif # with python3
|
||||||
|
|
||||||
%prep
|
%prep
|
||||||
%autosetup -n %{modname}-%{version} -p1
|
%setup -q -n %{modname}-%{version}
|
||||||
|
|
||||||
# python-unittest2 is now provided by "python" package and python-unittest is retired
|
# python-unittest2 is now provided by "python" package and python-unittest is retired
|
||||||
# adapt setup.py to reflect this fact downstream
|
# adapt setup.py to reflect this fact downstream
|
||||||
@ -55,59 +115,46 @@ sed -i "s/'unittest2', //" setup.py
|
|||||||
rm -rf %{modname}.egg-info
|
rm -rf %{modname}.egg-info
|
||||||
|
|
||||||
%build
|
%build
|
||||||
|
%if %{with python2}
|
||||||
|
%py2_build
|
||||||
|
%endif # with python2
|
||||||
|
%if %{with python3}
|
||||||
%py3_build
|
%py3_build
|
||||||
|
%endif # with python3
|
||||||
|
|
||||||
%install
|
%install
|
||||||
|
%if %{with python2}
|
||||||
|
%py2_install
|
||||||
|
%endif # with python2
|
||||||
|
%if %{with python3}
|
||||||
%py3_install
|
%py3_install
|
||||||
|
%endif # with python3
|
||||||
|
|
||||||
%check
|
%check
|
||||||
echo 'import pytest; __getattr__ = lambda _: pytest.skip("this test needs jwt")' > jwt.py
|
%if %{with python2}
|
||||||
%pytest -rs --ignore tests/oauth2/rfc6749/clients/test_service_application.py \
|
%{__python2} setup.py test
|
||||||
--ignore tests/oauth2/rfc6749/clients/test_web_application.py \
|
%endif # with python2
|
||||||
--ignore tests/oauth2/rfc6749/clients/test_mobile_application.py \
|
%if %{with python3}
|
||||||
--ignore tests/oauth2/rfc6749/clients/test_legacy_application.py \
|
%{__python3} setup.py test
|
||||||
--ignore tests/oauth2/rfc6749/clients/test_backend_application.py \
|
%endif # with python3
|
||||||
--ignore tests/oauth2/rfc6749/test_parameters.py
|
|
||||||
rm jwt.py
|
|
||||||
|
|
||||||
|
%if %{with python2}
|
||||||
|
%files -n python2-oauthlib
|
||||||
|
%doc README.rst
|
||||||
|
%license LICENSE
|
||||||
|
%{python2_sitelib}/%{modname}/
|
||||||
|
%{python2_sitelib}/%{modname}-%{version}*
|
||||||
|
%endif # with python2
|
||||||
|
|
||||||
|
%if %{with python3}
|
||||||
%files -n python3-oauthlib
|
%files -n python3-oauthlib
|
||||||
%doc README.rst
|
%doc README.rst
|
||||||
%license LICENSE
|
%license LICENSE
|
||||||
%{python3_sitelib}/%{modname}/
|
%{python3_sitelib}/%{modname}/
|
||||||
%{python3_sitelib}/%{modname}-%{version}-*
|
%{python3_sitelib}/%{modname}-%{version}-*
|
||||||
|
%endif # with python3
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Thu Nov 10 2022 TomasHalman <thalman@redhat.com> - 3.1.1-5
|
|
||||||
- RFC5849 oauth1 signature base_string_uri doesn't parse IPv6 addresses
|
|
||||||
Resolves: rhbz#2133805
|
|
||||||
|
|
||||||
* Mon Oct 24 2022 TomasHalman <thalman@redhat.com> - 3.1.1-4
|
|
||||||
- Resolves: rhbz#2133805 - fix for CVE-2022-36087
|
|
||||||
|
|
||||||
* Tue Aug 9 2022 TomasHalman <thalman@redhat.com> - 3.1.1-3
|
|
||||||
- Remove RSA support
|
|
||||||
- Remove build dependency on blinker
|
|
||||||
Resolves: rhbz#1984046 - python-oauthlib depends on jwt for RSA
|
|
||||||
|
|
||||||
* Tue Aug 10 2021 Mohan Boddu <mboddu@redhat.com> - 3.1.1-2
|
|
||||||
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
|
|
||||||
Related: rhbz#1991688
|
|
||||||
|
|
||||||
* Mon Jun 28 2021 Jakub Hrozek <jhrozek@redhat.com> - 3.1.1-1
|
|
||||||
- Resolves: rhbz#1935433 - python-oauthlib implements and/or uses the
|
|
||||||
deprecated SHA1 algorithm by default
|
|
||||||
|
|
||||||
* Mon May 31 2021 Miro Hrončok <mhroncok@redhat.com> - 3.1.0-2
|
|
||||||
- Remove the python3-oauthlib+signedtoken package
|
|
||||||
- When building, skip tests that require jwt
|
|
||||||
- Resolves: rhbz#1966407 - Drop python-jwt dependency from python-oauthlib
|
|
||||||
|
|
||||||
* Tue May 25 2021 Jakub Hrozek <jhrozek@redhat.com> - 3.1.0-1
|
|
||||||
- Resolves: rhbz#1922352 - python-oauthlib requires python-mock
|
|
||||||
- Update to upstream 3.1.0
|
|
||||||
- Gets rid of obsolete python-nose dependency
|
|
||||||
- Nuke the python2/python3 conditionals, let's only support python3
|
|
||||||
|
|
||||||
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 3.0.2-10
|
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 3.0.2-10
|
||||||
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
|
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
|
||||||
|
|
||||||
|
2
sources
2
sources
@ -1 +1 @@
|
|||||||
SHA512 (oauthlib-3.1.1.tar.gz) = 7f18bcbd51fe209b8ceecf0813f18b25f1786745779288ffed116f2759d9e071cef069ffb6d7e03ed0ad606bd056904f924db4245b05f246a758b78214966f39
|
SHA512 (oauthlib-3.0.2.tar.gz) = 7a91696d4fa753c2075449a9ca6122d49042ec4a318051f75c6c80b4b77caac17a91e7c4e861f6c1d697c5c80b91f7d4a0c95736cbe386857faad8467b161310
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
#!/bin/bash -x
|
|
||||||
|
|
||||||
die () {
|
|
||||||
echo "$1" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
SITEDIR=`python3 -c 'import sysconfig; print(sysconfig.get_paths()["purelib"])'`
|
|
||||||
if [ "$SITEDIR" == "" ]; then
|
|
||||||
die "Can't locate python site dir"
|
|
||||||
fi
|
|
||||||
|
|
||||||
#
|
|
||||||
# install dependencies (pytest & blinker)
|
|
||||||
#
|
|
||||||
rm -rf venv
|
|
||||||
python3 -m venv venv
|
|
||||||
. venv/bin/activate
|
|
||||||
pip install -r requirements-tests.txt
|
|
||||||
|
|
||||||
|
|
||||||
# rename source code directory to be sure that we are
|
|
||||||
# testing files from our rpm
|
|
||||||
cd source || die "Missing source directory!"
|
|
||||||
if [ -d oauthlib ] ; then
|
|
||||||
mv oauthlib oauthlib.backup || die "Can't rename/hide source code directory!"
|
|
||||||
fi
|
|
||||||
ln -s $SITEDIR/oauthlib || die "Can't locate installed library"
|
|
||||||
|
|
||||||
#
|
|
||||||
# run upstream tests, skip jwt tests
|
|
||||||
#
|
|
||||||
echo 'import pytest; __getattr__ = lambda _: pytest.skip("this test needs jwt")' > jwt.py
|
|
||||||
pytest tests -p no:warnings --ignore tests/oauth2/rfc6749/clients/test_service_application.py | tee oauthlib.log
|
|
||||||
RESULT=${PIPESTATUS[0]}
|
|
||||||
|
|
||||||
#
|
|
||||||
# cleanup
|
|
||||||
#
|
|
||||||
rm jwt.py
|
|
||||||
if [ -L oauthlib ] ; then
|
|
||||||
rm oauthlib
|
|
||||||
fi
|
|
||||||
if [ -d oauthlib.backup ] ; then
|
|
||||||
mv oauthlib.backup oauthlib
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit $RESULT
|
|
@ -1,2 +0,0 @@
|
|||||||
blinker==1.5
|
|
||||||
pytest==7.2
|
|
@ -1,17 +0,0 @@
|
|||||||
---
|
|
||||||
- hosts: localhost
|
|
||||||
roles:
|
|
||||||
- role: standard-test-source
|
|
||||||
tags:
|
|
||||||
- always
|
|
||||||
|
|
||||||
- role: standard-test-basic
|
|
||||||
tags:
|
|
||||||
- classic
|
|
||||||
required_packages:
|
|
||||||
- python3-oauthlib
|
|
||||||
tests:
|
|
||||||
- oauthtests:
|
|
||||||
dir: .
|
|
||||||
run: ./oauthtests.sh
|
|
||||||
save-files: ["source/*.log"]
|
|
Loading…
Reference in New Issue
Block a user