badauth 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- badauth-0.1.0/LICENSE +21 -0
- badauth-0.1.0/MANIFEST.in +2 -0
- badauth-0.1.0/PKG-INFO +32 -0
- badauth-0.1.0/README.md +1 -0
- badauth-0.1.0/badauth/__init__.py +16 -0
- badauth-0.1.0/badauth/_version.py +8 -0
- badauth-0.1.0/badauth/common/__init__.py +0 -0
- badauth-0.1.0/badauth/common/clientauthalgo.py +49 -0
- badauth-0.1.0/badauth/common/constants.py +64 -0
- badauth-0.1.0/badauth/common/credentials/__init__.py +390 -0
- badauth-0.1.0/badauth/common/credentials/credssp.py +24 -0
- badauth-0.1.0/badauth/common/credentials/kerberos.py +177 -0
- badauth-0.1.0/badauth/common/credentials/ntlm.py +154 -0
- badauth-0.1.0/badauth/common/credentials/spnego.py +36 -0
- badauth-0.1.0/badauth/common/credentials/spnegoex.py +27 -0
- badauth-0.1.0/badauth/common/subprotocols/__init__.py +31 -0
- badauth-0.1.0/badauth/common/subprotocols/custom.py +18 -0
- badauth-0.1.0/badauth/common/subprotocols/native.py +11 -0
- badauth-0.1.0/badauth/common/subprotocols/sspi.py +14 -0
- badauth-0.1.0/badauth/common/subprotocols/sspiproxy.py +42 -0
- badauth-0.1.0/badauth/common/subprotocols/wsnet.py +11 -0
- badauth-0.1.0/badauth/common/subprotocols/wsnetdirect.py +21 -0
- badauth-0.1.0/badauth/common/winapi/__init__.py +0 -0
- badauth-0.1.0/badauth/common/winapi/constants.py +180 -0
- badauth-0.1.0/badauth/common/winapi/functiondefs.py +337 -0
- badauth-0.1.0/badauth/common/winapi/token.py +44 -0
- badauth-0.1.0/badauth/common/winapi/winsspi.py +67 -0
- badauth-0.1.0/badauth/protocols/__init__.py +57 -0
- badauth-0.1.0/badauth/protocols/credssp/__init__.py +4 -0
- badauth-0.1.0/badauth/protocols/credssp/client/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/credssp/client/native.py +319 -0
- badauth-0.1.0/badauth/protocols/credssp/messages/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/credssp/messages/asn1_structs.py +136 -0
- badauth-0.1.0/badauth/protocols/credssp/messages/remcredguard.py +101 -0
- badauth-0.1.0/badauth/protocols/kerberos/__init__.py +4 -0
- badauth-0.1.0/badauth/protocols/kerberos/client/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/kerberos/client/native.py +286 -0
- badauth-0.1.0/badauth/protocols/kerberos/client/sspi.py +100 -0
- badauth-0.1.0/badauth/protocols/kerberos/client/sspiproxy.py +155 -0
- badauth-0.1.0/badauth/protocols/kerberos/client/wsnet.py +160 -0
- badauth-0.1.0/badauth/protocols/kerberos/client/wsnetdirect.py +194 -0
- badauth-0.1.0/badauth/protocols/kerberos/gssapi.py +558 -0
- badauth-0.1.0/badauth/protocols/kerberos/gssapismb.py +412 -0
- badauth-0.1.0/badauth/protocols/ntlm/__init__.py +4 -0
- badauth-0.1.0/badauth/protocols/ntlm/client/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/ntlm/client/native.py +438 -0
- badauth-0.1.0/badauth/protocols/ntlm/client/sspi.py +92 -0
- badauth-0.1.0/badauth/protocols/ntlm/client/sspiproxy.py +76 -0
- badauth-0.1.0/badauth/protocols/ntlm/client/wsnet.py +103 -0
- badauth-0.1.0/badauth/protocols/ntlm/client/wsnetdirect.py +129 -0
- badauth-0.1.0/badauth/protocols/ntlm/creds_calc.py +594 -0
- badauth-0.1.0/badauth/protocols/ntlm/messages/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/ntlm/messages/authenticate.py +235 -0
- badauth-0.1.0/badauth/protocols/ntlm/messages/challenge.py +148 -0
- badauth-0.1.0/badauth/protocols/ntlm/messages/negotiate.py +169 -0
- badauth-0.1.0/badauth/protocols/ntlm/relay/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/ntlm/relay/native.py +449 -0
- badauth-0.1.0/badauth/protocols/ntlm/structures/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/ntlm/structures/avpair.py +98 -0
- badauth-0.1.0/badauth/protocols/ntlm/structures/challenge_response.py +208 -0
- badauth-0.1.0/badauth/protocols/ntlm/structures/fields.py +24 -0
- badauth-0.1.0/badauth/protocols/ntlm/structures/negotiate_flags.py +72 -0
- badauth-0.1.0/badauth/protocols/ntlm/structures/ntlmssp_message_signature.py +33 -0
- badauth-0.1.0/badauth/protocols/ntlm/structures/ntlmssp_message_signature_noext.py +37 -0
- badauth-0.1.0/badauth/protocols/ntlm/structures/serverinfo.py +154 -0
- badauth-0.1.0/badauth/protocols/ntlm/structures/version.py +100 -0
- badauth-0.1.0/badauth/protocols/ntlm/templates/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/ntlm/templates/client.py +89 -0
- badauth-0.1.0/badauth/protocols/ntlm/templates/server.py +40 -0
- badauth-0.1.0/badauth/protocols/spnego/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/spnego/client/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/spnego/client/native.py +288 -0
- badauth-0.1.0/badauth/protocols/spnego/messages/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/spnego/messages/asn1_structs.py +166 -0
- badauth-0.1.0/badauth/protocols/spnego/relay/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/spnego/relay/native.py +326 -0
- badauth-0.1.0/badauth/protocols/spnegoex/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/spnegoex/client/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/spnegoex/client/native.py +141 -0
- badauth-0.1.0/badauth/protocols/spnegoex/protocol/__init__.py +0 -0
- badauth-0.1.0/badauth/protocols/spnegoex/protocol/messages.py +580 -0
- badauth-0.1.0/badauth/utils/__init__.py +0 -0
- badauth-0.1.0/badauth/utils/hexdump.py +47 -0
- badauth-0.1.0/badauth/utils/paramprocessor.py +12 -0
- badauth-0.1.0/badauth/utils/timestamp.py +17 -0
- badauth-0.1.0/badauth.egg-info/PKG-INFO +32 -0
- badauth-0.1.0/badauth.egg-info/SOURCES.txt +92 -0
- badauth-0.1.0/badauth.egg-info/dependency_links.txt +1 -0
- badauth-0.1.0/badauth.egg-info/not-zip-safe +1 -0
- badauth-0.1.0/badauth.egg-info/requires.txt +4 -0
- badauth-0.1.0/badauth.egg-info/top_level.txt +1 -0
- badauth-0.1.0/pyproject.toml +3 -0
- badauth-0.1.0/setup.cfg +4 -0
- badauth-0.1.0/setup.py +58 -0
badauth-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2022 Tamas Jos (@skelsec)
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
badauth-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: badauth
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unified authentication library
|
|
5
|
+
Home-page: https://github.com/CravateRouge/badauth
|
|
6
|
+
Author: Tamas Jos
|
|
7
|
+
Author-email: info@skelsecprojects.com
|
|
8
|
+
Maintainer: Baptiste Crépin
|
|
9
|
+
Maintainer-email: baptiste@cravaterouge.com
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Requires-Python: >=3.7
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: unicrypto>=0.0.10
|
|
17
|
+
Requires-Dist: asn1crypto>=1.3.0
|
|
18
|
+
Requires-Dist: asysocks>=0.2.11
|
|
19
|
+
Requires-Dist: kerbad>=0.5.3
|
|
20
|
+
Dynamic: author
|
|
21
|
+
Dynamic: author-email
|
|
22
|
+
Dynamic: classifier
|
|
23
|
+
Dynamic: description
|
|
24
|
+
Dynamic: home-page
|
|
25
|
+
Dynamic: license-file
|
|
26
|
+
Dynamic: maintainer
|
|
27
|
+
Dynamic: maintainer-email
|
|
28
|
+
Dynamic: requires-dist
|
|
29
|
+
Dynamic: requires-python
|
|
30
|
+
Dynamic: summary
|
|
31
|
+
|
|
32
|
+
Unified authentication library
|
badauth-0.1.0/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# badauth
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
#
|
|
3
|
+
# Author:
|
|
4
|
+
# Tamas Jos (@skelsec)
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger('badauth')
|
|
10
|
+
handler = logging.StreamHandler()
|
|
11
|
+
formatter = logging.Formatter(
|
|
12
|
+
'%(asctime)s %(name)-12s %(levelname)-8s %(message)s')
|
|
13
|
+
handler.setFormatter(formatter)
|
|
14
|
+
logger.addHandler(handler)
|
|
15
|
+
logger.setLevel(logging.INFO)
|
|
16
|
+
logger.propagate = False
|
|
File without changes
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from typing import Tuple
|
|
2
|
+
from badauth.common.winapi.constants import ISC_REQ
|
|
3
|
+
from badauth.common.credentials import UniCredential
|
|
4
|
+
|
|
5
|
+
class ClientAuthAlgo:
|
|
6
|
+
def __init__(self, credential:UniCredential):
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
#def is_guest(self):
|
|
10
|
+
# raise NotImplementedError()
|
|
11
|
+
|
|
12
|
+
def get_seq_number(self) -> int:
|
|
13
|
+
"""Returns the !INITIAL! sequence number"""
|
|
14
|
+
raise NotImplementedError()
|
|
15
|
+
|
|
16
|
+
def get_session_key(self) -> bytes:
|
|
17
|
+
"""Returns session key bytes"""
|
|
18
|
+
raise NotImplementedError()
|
|
19
|
+
|
|
20
|
+
async def encrypt(self, data:bytes, sequence_no:int):
|
|
21
|
+
"""Encryptes message"""
|
|
22
|
+
raise NotImplementedError()
|
|
23
|
+
|
|
24
|
+
async def decrypt(self, data:bytes, sequence_no:int, direction='init', auth_data=None) -> Tuple[bytes, Exception]:
|
|
25
|
+
"""Decrypts message. Also performs integrity checking."""
|
|
26
|
+
raise NotImplementedError()
|
|
27
|
+
|
|
28
|
+
async def sign(self, data:bytes, message_no:int, direction:str=None, reset_cipher:bool = False) -> bytes:
|
|
29
|
+
"""Singing outgoing messages. The reset_cipher parameter is needed for calculating mechListMIC."""
|
|
30
|
+
raise NotImplementedError()
|
|
31
|
+
|
|
32
|
+
async def verify(self, data:bytes, signature:bytes) -> bool:
|
|
33
|
+
"""Verifying message signature"""
|
|
34
|
+
raise NotImplementedError()
|
|
35
|
+
|
|
36
|
+
def signing_needed(self) -> bool:
|
|
37
|
+
"""Returns wether signing is negotiated for this client"""
|
|
38
|
+
raise NotImplementedError()
|
|
39
|
+
|
|
40
|
+
def encryption_needed(self) -> bool:
|
|
41
|
+
"""Returns wether encryption is negotiated for this client"""
|
|
42
|
+
raise NotImplementedError()
|
|
43
|
+
|
|
44
|
+
def get_session_key(self) -> bytes:
|
|
45
|
+
"""Returns the session key bytes"""
|
|
46
|
+
raise NotImplementedError()
|
|
47
|
+
|
|
48
|
+
async def authenticate(self, authData:bytes, flags:ISC_REQ = None, cb_data:bytes = None, spn:str=None): # -> Tuple[bytes, bool, Exception]
|
|
49
|
+
raise NotImplementedError()
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import enum
|
|
2
|
+
|
|
3
|
+
class asyauthProtocol(enum.Enum):
|
|
4
|
+
NONE = 'NONE'
|
|
5
|
+
SIMPLE = 'SIMPLE'
|
|
6
|
+
PLAIN = 'PLAIN'
|
|
7
|
+
SICILY = 'SICILY'
|
|
8
|
+
NTLM = 'NTLM'
|
|
9
|
+
KERBEROS = 'KERBEROS'
|
|
10
|
+
CREDSSP = 'CREDSSP'
|
|
11
|
+
SPNEGO = 'SPNEGO'
|
|
12
|
+
SPNEGOEX = 'SPNEGOEX'
|
|
13
|
+
SSL = 'SSL' # SSL/TLS schannel later
|
|
14
|
+
SYS = 'SYS' #NFS
|
|
15
|
+
NULL = 'NULL' #NFS
|
|
16
|
+
SPNEGO_NTLM = 'SPNEGO_NTLM'
|
|
17
|
+
SPNEGO_KERBEROS = 'SPNEGO_KERBEROS'
|
|
18
|
+
CREDSSP_NTLM = 'CREDSSP_NTLM'
|
|
19
|
+
CREDSSP_KERBEROS = 'CREDSSP_KERBEROS'
|
|
20
|
+
|
|
21
|
+
class asyauthSubProtocol(enum.Enum):
|
|
22
|
+
NATIVE = 'NATIVE'
|
|
23
|
+
SSPI = 'SSPI'
|
|
24
|
+
WSNET = 'WSNET'
|
|
25
|
+
WSNETDIRECT = 'WSNETDIRECT'
|
|
26
|
+
SSPIPROXY = 'SSPIPROXY'
|
|
27
|
+
CUSTOM = 'CUSTOM'
|
|
28
|
+
|
|
29
|
+
class asyauthSecret(enum.Enum):
|
|
30
|
+
NONE = 'NONE'
|
|
31
|
+
PASSWORD = 'PASSWORD'
|
|
32
|
+
PASS = 'PASS'
|
|
33
|
+
PW = 'PW'
|
|
34
|
+
PWB64 = 'PWB64'
|
|
35
|
+
PWPROMPT = 'PWPROMPT'
|
|
36
|
+
PWHEX = 'PWHEX'
|
|
37
|
+
LM = 'LM'
|
|
38
|
+
NT = 'NT'
|
|
39
|
+
RC4 = 'RC4'
|
|
40
|
+
AES = 'AES'
|
|
41
|
+
CCACHE = 'CCACHE'
|
|
42
|
+
CCACHEHEX = 'CCACHEHEX'
|
|
43
|
+
CCACHEB64 = 'CCACHEB64'
|
|
44
|
+
KEYTAB = 'KEYTAB'
|
|
45
|
+
KEYTABHEX = 'KEYTABHEX'
|
|
46
|
+
KEYTABB64 = 'KEYTABB64'
|
|
47
|
+
PFX = 'PFX'
|
|
48
|
+
PFXB64 = 'PFXB64'
|
|
49
|
+
PFXHEX = 'PFXHEX'
|
|
50
|
+
PFXSTR = 'PFXSTR'
|
|
51
|
+
PEM = 'PEM'
|
|
52
|
+
CERTSTORE = 'CERTSTORE'
|
|
53
|
+
KIRBI = 'KIRBI'
|
|
54
|
+
KIRBIHEX = 'KIRBIHEX'
|
|
55
|
+
KIRBIB64 = 'KIRBIB64'
|
|
56
|
+
DES = 'DES'
|
|
57
|
+
TDES = 'TDES'
|
|
58
|
+
DES3 = 'DES3'
|
|
59
|
+
SSHPRIVKEY = 'SSHPRIVKEY'
|
|
60
|
+
SSHPRIVKEYSTR = 'SSHPRIVKEYSTR'
|
|
61
|
+
SSHPRIVKEYB64 = 'SSHPRIVKEYB64'
|
|
62
|
+
SYS = 'SYS' #NFS
|
|
63
|
+
NULL = 'NULL' #NFS
|
|
64
|
+
WSNET = 'WSNET'
|
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import platform
|
|
3
|
+
import copy
|
|
4
|
+
from urllib.parse import urlparse, parse_qs, unquote
|
|
5
|
+
from badauth.utils.paramprocessor import str_one, int_one, bool_one
|
|
6
|
+
from badauth.common.constants import asyauthSecret, asyauthProtocol, asyauthSubProtocol
|
|
7
|
+
from badauth.common.subprotocols import SubProtocol, SubProtocolNative, SubProtocolSSPI
|
|
8
|
+
|
|
9
|
+
class UniCredential:
|
|
10
|
+
def __init__(self, secret:str = None, username:str = None, domain:str = None, stype:asyauthSecret = asyauthSecret.NONE, protocol:asyauthProtocol = None, subprotocol:SubProtocol = SubProtocolNative(), **kwargs):
|
|
11
|
+
self.domain = domain
|
|
12
|
+
self.username = username
|
|
13
|
+
self.secret = secret
|
|
14
|
+
self.stype = stype
|
|
15
|
+
self.protocol = protocol
|
|
16
|
+
self.subprotocol = subprotocol
|
|
17
|
+
self.metadata = kwargs
|
|
18
|
+
|
|
19
|
+
if stype in [asyauthSecret.PASS, asyauthSecret.PW]:
|
|
20
|
+
self.stype = asyauthSecret.PASSWORD
|
|
21
|
+
elif stype == asyauthSecret.PWB64:
|
|
22
|
+
self.stype = asyauthSecret.PASSWORD
|
|
23
|
+
self.secret = base64.b64decode(self.secret).decode()
|
|
24
|
+
elif stype == asyauthSecret.PWHEX:
|
|
25
|
+
self.stype = asyauthSecret.PASSWORD
|
|
26
|
+
self.secret = bytes.fromhex(self.secret).decode()
|
|
27
|
+
elif stype == asyauthSecret.PWPROMPT:
|
|
28
|
+
import getpass
|
|
29
|
+
self.stype = asyauthSecret.PASSWORD
|
|
30
|
+
self.secret = getpass.getpass('Enter password: ')
|
|
31
|
+
|
|
32
|
+
def build_context(self, protocol=None, target = None, **kwargs):
|
|
33
|
+
if protocol is None:
|
|
34
|
+
protocol = self.protocol
|
|
35
|
+
|
|
36
|
+
if protocol == asyauthProtocol.NTLM:
|
|
37
|
+
if self.subprotocol.type == asyauthSubProtocol.NATIVE:
|
|
38
|
+
from badauth.common.credentials.ntlm import NTLMCredential
|
|
39
|
+
return NTLMCredential(self.secret, self.username, self.domain, self.stype, subprotocol=self.subprotocol, **kwargs).build_context()
|
|
40
|
+
else:
|
|
41
|
+
raise Exception('Unsupported subprotocol "%s"' % self.subprotocol)
|
|
42
|
+
|
|
43
|
+
elif protocol == asyauthProtocol.KERBEROS:
|
|
44
|
+
if self.subprotocol.type == asyauthSubProtocol.NATIVE:
|
|
45
|
+
from badauth.common.credentials.kerberos import KerberosCredential
|
|
46
|
+
return KerberosCredential(
|
|
47
|
+
self.secret,
|
|
48
|
+
self.username,
|
|
49
|
+
self.domain,
|
|
50
|
+
self.stype,
|
|
51
|
+
subprotocol=self.subprotocol,
|
|
52
|
+
target=target,
|
|
53
|
+
**kwargs
|
|
54
|
+
).build_context()
|
|
55
|
+
else:
|
|
56
|
+
raise Exception('Unsupported subprotocol "%s"' % self.subprotocol)
|
|
57
|
+
|
|
58
|
+
elif protocol == asyauthProtocol.SPNEGO:
|
|
59
|
+
if self.subprotocol.type == asyauthSubProtocol.NATIVE:
|
|
60
|
+
from badauth.common.credentials.spnego import SPNEGOCredential
|
|
61
|
+
return SPNEGOCredential([self.build_context(target=target, **kwargs)], subprotocol=self.subprotocol).build_context()
|
|
62
|
+
else:
|
|
63
|
+
raise Exception('Unsupported subprotocol "%s"' % self.subprotocol)
|
|
64
|
+
|
|
65
|
+
elif protocol == asyauthProtocol.SPNEGOEX:
|
|
66
|
+
if self.subprotocol.type == asyauthSubProtocol.NATIVE:
|
|
67
|
+
from badauth.common.credentials.spnegoex import SPNEGOEXCredential
|
|
68
|
+
return SPNEGOEXCredential([self.build_context(target=target, **kwargs)], subprotocol=self.subprotocol).build_context()
|
|
69
|
+
else:
|
|
70
|
+
raise Exception('Unsupported subprotocol "%s"' % self.subprotocol)
|
|
71
|
+
|
|
72
|
+
elif protocol == asyauthProtocol.CREDSSP:
|
|
73
|
+
if self.subprotocol.type == asyauthSubProtocol.NATIVE:
|
|
74
|
+
from badauth.common.credentials.credssp import CREDSSPCredential
|
|
75
|
+
return CREDSSPCredential([self.build_context(target=target, **kwargs)], subprotocol=self.subprotocol).build_context()
|
|
76
|
+
else:
|
|
77
|
+
raise Exception('Unsupported subprotocol "%s"' % self.subprotocol)
|
|
78
|
+
|
|
79
|
+
else:
|
|
80
|
+
return copy.deepcopy(self)
|
|
81
|
+
|
|
82
|
+
@staticmethod
|
|
83
|
+
def get_url_params():
|
|
84
|
+
return {
|
|
85
|
+
'timeout' : int_one,
|
|
86
|
+
'dns' : str_one,
|
|
87
|
+
'dnsc' : str_one, #cross-domain DNS
|
|
88
|
+
'dc' : str_one,
|
|
89
|
+
'dcc' : str_one, #cross-domain DC IP
|
|
90
|
+
'realmc' : str_one, #cross-domain realm
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@staticmethod
|
|
94
|
+
def from_url(connection_url):
|
|
95
|
+
from asysocks.unicomm.common.target import UniTarget, UniProto
|
|
96
|
+
|
|
97
|
+
secret = None
|
|
98
|
+
username = None
|
|
99
|
+
domain = None
|
|
100
|
+
stype = asyauthSecret.NONE
|
|
101
|
+
protocol = asyauthProtocol.NONE
|
|
102
|
+
subprotocol = SubProtocolNative()
|
|
103
|
+
url_e = urlparse(connection_url)
|
|
104
|
+
url_dict = url_e._asdict()
|
|
105
|
+
for prop, val in url_dict.items():
|
|
106
|
+
if type(val) is str and prop != 'query':
|
|
107
|
+
url_dict[prop] = unquote(val)
|
|
108
|
+
url_e = url_e._replace(**url_dict)
|
|
109
|
+
schemes = url_e.scheme.upper().split('+')
|
|
110
|
+
if len(schemes) == 1:
|
|
111
|
+
try:
|
|
112
|
+
protocol = asyauthProtocol(schemes)
|
|
113
|
+
except:
|
|
114
|
+
pass
|
|
115
|
+
else:
|
|
116
|
+
auth_tags = schemes[1].replace('-','_')
|
|
117
|
+
try:
|
|
118
|
+
protocol = asyauthProtocol(auth_tags)
|
|
119
|
+
except:
|
|
120
|
+
auth_tags = schemes[1].split('-')
|
|
121
|
+
if len(auth_tags) > 1:
|
|
122
|
+
try:
|
|
123
|
+
spt = asyauthSubProtocol(auth_tags[0])
|
|
124
|
+
except:
|
|
125
|
+
protocol = asyauthProtocol(auth_tags[0])
|
|
126
|
+
stype = asyauthSecret(auth_tags[1])
|
|
127
|
+
else:
|
|
128
|
+
protocol = asyauthProtocol(auth_tags[1])
|
|
129
|
+
query = None
|
|
130
|
+
if url_e.query is not None:
|
|
131
|
+
query = parse_qs(url_e.query)
|
|
132
|
+
subprotocol = SubProtocol.from_url_params(spt, query)
|
|
133
|
+
|
|
134
|
+
else:
|
|
135
|
+
try:
|
|
136
|
+
spt = asyauthSubProtocol(auth_tags[0])
|
|
137
|
+
protocol = asyauthProtocol.NTLM
|
|
138
|
+
except:
|
|
139
|
+
protocol = asyauthProtocol(auth_tags[0])
|
|
140
|
+
|
|
141
|
+
if url_e.username is not None:
|
|
142
|
+
if url_e.username.find('\\') != -1:
|
|
143
|
+
domain, username = url_e.username.split('\\')
|
|
144
|
+
if domain == '.':
|
|
145
|
+
domain = None
|
|
146
|
+
else:
|
|
147
|
+
domain = None
|
|
148
|
+
username = url_e.username
|
|
149
|
+
|
|
150
|
+
secret = url_e.password
|
|
151
|
+
credobj = None
|
|
152
|
+
if protocol == asyauthProtocol.KERBEROS:
|
|
153
|
+
from badauth.common.credentials.kerberos import KerberosCredential
|
|
154
|
+
credobj = KerberosCredential
|
|
155
|
+
|
|
156
|
+
elif protocol in [asyauthProtocol.NTLM, asyauthProtocol.SICILY]:
|
|
157
|
+
from badauth.common.credentials.ntlm import NTLMCredential
|
|
158
|
+
credobj = NTLMCredential
|
|
159
|
+
|
|
160
|
+
extraparams = {}
|
|
161
|
+
if credobj is not None:
|
|
162
|
+
extraparams = credobj.get_url_params()
|
|
163
|
+
|
|
164
|
+
paramstemplate = UniCredential.get_url_params()
|
|
165
|
+
params = dict.fromkeys(UniCredential.get_url_params(),None)
|
|
166
|
+
extra = dict.fromkeys(extraparams.keys(),None)
|
|
167
|
+
proxy_present = False
|
|
168
|
+
if url_e.query is not None:
|
|
169
|
+
query = parse_qs(url_e.query)
|
|
170
|
+
for k in query:
|
|
171
|
+
if k.startswith('proxy') is True:
|
|
172
|
+
proxy_present = True
|
|
173
|
+
if k in params:
|
|
174
|
+
params[k] = paramstemplate[k](query[k])
|
|
175
|
+
if k in extraparams:
|
|
176
|
+
extra[k] = extraparams[k](query[k])
|
|
177
|
+
|
|
178
|
+
if protocol in [asyauthProtocol.NTLM, asyauthProtocol.SICILY]:
|
|
179
|
+
res = credobj(
|
|
180
|
+
secret,
|
|
181
|
+
username,
|
|
182
|
+
domain,
|
|
183
|
+
stype,
|
|
184
|
+
subprotocol=subprotocol,
|
|
185
|
+
**extra
|
|
186
|
+
)
|
|
187
|
+
if protocol == asyauthProtocol.SICILY:
|
|
188
|
+
res.protocol = asyauthProtocol.SICILY
|
|
189
|
+
return res
|
|
190
|
+
|
|
191
|
+
elif protocol == asyauthProtocol.KERBEROS:
|
|
192
|
+
proxies = None
|
|
193
|
+
if proxy_present is True:
|
|
194
|
+
from asysocks.unicomm.common.proxy import UniProxyTarget
|
|
195
|
+
proxies = UniProxyTarget.from_url_params(url_e.query, url_e.hostname,endpoint_port=88)
|
|
196
|
+
|
|
197
|
+
target = None
|
|
198
|
+
if extra['dc'] is not None:
|
|
199
|
+
target = UniTarget(extra['dc'], 88, UniProto.CLIENT_TCP, proxies = proxies, dns=params['dns'], dc_ip=extra['dc'])
|
|
200
|
+
|
|
201
|
+
cross_target = None
|
|
202
|
+
if extra['dcc'] is not None:
|
|
203
|
+
cross_target = UniTarget(extra['dcc'], 88, UniProto.CLIENT_TCP, proxies = proxies, dns=params['dnsc'], dc_ip=extra['dcc'])
|
|
204
|
+
|
|
205
|
+
etypes = extra['etype']
|
|
206
|
+
|
|
207
|
+
return credobj(
|
|
208
|
+
secret,
|
|
209
|
+
username,
|
|
210
|
+
domain,
|
|
211
|
+
stype,
|
|
212
|
+
target = target,
|
|
213
|
+
altname = extra['altname'],
|
|
214
|
+
altdomain = extra['altdomain'],
|
|
215
|
+
certdata=extra['certdata'],
|
|
216
|
+
keydata=extra['keydata'],
|
|
217
|
+
etypes = etypes,
|
|
218
|
+
subprotocol = subprotocol,
|
|
219
|
+
cross_target = cross_target,
|
|
220
|
+
cross_realm = extra['realmc'],
|
|
221
|
+
)
|
|
222
|
+
else:
|
|
223
|
+
return UniCredential(
|
|
224
|
+
secret,
|
|
225
|
+
username,
|
|
226
|
+
domain,
|
|
227
|
+
stype,
|
|
228
|
+
protocol,
|
|
229
|
+
subprotocol
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
def __str__(self):
|
|
233
|
+
import enum
|
|
234
|
+
t = '==== UniCredential ====\r\n'
|
|
235
|
+
for k in self.__dict__:
|
|
236
|
+
val = self.__dict__[k]
|
|
237
|
+
if isinstance(val, enum.IntFlag):
|
|
238
|
+
val = val
|
|
239
|
+
elif isinstance(val, enum.Enum):
|
|
240
|
+
val = val.name
|
|
241
|
+
|
|
242
|
+
t += '%s: %s\r\n' % (k, str(val))
|
|
243
|
+
|
|
244
|
+
return t
|
|
245
|
+
|
|
246
|
+
@staticmethod
|
|
247
|
+
def get_sspi_ntlm():
|
|
248
|
+
"""Returns an NTLM credential object matching the current user (Windows only)"""
|
|
249
|
+
if platform.system() != 'Windows':
|
|
250
|
+
raise Exception('This function only works on Windows systems!')
|
|
251
|
+
from winacl.functions.highlevel import get_logon_info
|
|
252
|
+
from badauth.common.credentials.ntlm import NTLMCredential
|
|
253
|
+
userinfo = get_logon_info()
|
|
254
|
+
return NTLMCredential(
|
|
255
|
+
None,
|
|
256
|
+
userinfo['username'],
|
|
257
|
+
userinfo['domain'],
|
|
258
|
+
stype=asyauthSecret.NONE,
|
|
259
|
+
subprotocol = SubProtocolSSPI()
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
@staticmethod
|
|
263
|
+
def get_sspi_kerberos():
|
|
264
|
+
"""Returns a Kerberos credential object matching the current user (Windows only)"""
|
|
265
|
+
if platform.system() != 'Windows':
|
|
266
|
+
raise Exception('This function only works on Windows systems!')
|
|
267
|
+
from winacl.functions.highlevel import get_logon_info
|
|
268
|
+
from badauth.common.credentials.kerberos import KerberosCredential
|
|
269
|
+
from asysocks.unicomm.common.target import UniTarget, UniProto
|
|
270
|
+
userinfo = get_logon_info()
|
|
271
|
+
dctarget = UniTarget(
|
|
272
|
+
userinfo['logonserver'],
|
|
273
|
+
88,
|
|
274
|
+
UniProto.CLIENT_TCP,
|
|
275
|
+
dc_ip=userinfo['logonserver'],
|
|
276
|
+
domain = userinfo['dnsdomainname'],
|
|
277
|
+
)
|
|
278
|
+
return KerberosCredential(
|
|
279
|
+
None,
|
|
280
|
+
userinfo['username'],
|
|
281
|
+
userinfo['dnsdomainname'],
|
|
282
|
+
stype=asyauthSecret.NONE,
|
|
283
|
+
target=dctarget,
|
|
284
|
+
subprotocol = SubProtocolSSPI()
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
@staticmethod
|
|
288
|
+
def get_sspi(authtype:str):
|
|
289
|
+
if platform.system() != 'Windows':
|
|
290
|
+
raise Exception('This function only works on Windows systems!')
|
|
291
|
+
if authtype.upper() == 'NTLM':
|
|
292
|
+
credobj = UniCredential.get_sspi_ntlm()
|
|
293
|
+
elif authtype.upper() == 'KERBEROS':
|
|
294
|
+
credobj = UniCredential.get_sspi_kerberos()
|
|
295
|
+
else:
|
|
296
|
+
raise Exception('Only NTLM or KERBEROS auth types supported here!')
|
|
297
|
+
return credobj
|
|
298
|
+
|
|
299
|
+
@staticmethod
|
|
300
|
+
def get_sspi_spnego(authtype:str):
|
|
301
|
+
"""Returns a SPNEGO credential object matching the current user (Windows only)"""
|
|
302
|
+
if platform.system() != 'Windows':
|
|
303
|
+
raise Exception('This function only works on Windows systems!')
|
|
304
|
+
from badauth.common.credentials.spnego import SPNEGOCredential
|
|
305
|
+
credobj = UniCredential.get_sspi(authtype)
|
|
306
|
+
return SPNEGOCredential([credobj])
|
|
307
|
+
|
|
308
|
+
@staticmethod
|
|
309
|
+
def get_sspi_spnego(authtype:str):
|
|
310
|
+
"""Returns a CREDSSP credential object matching the current user (Windows only)"""
|
|
311
|
+
if platform.system() != 'Windows':
|
|
312
|
+
raise Exception('This function only works on Windows systems!')
|
|
313
|
+
from badauth.common.credentials.credssp import CREDSSPCredential
|
|
314
|
+
credobj = UniCredential.get_sspi(authtype)
|
|
315
|
+
return CREDSSPCredential([credobj])
|
|
316
|
+
|
|
317
|
+
@staticmethod
|
|
318
|
+
def get_help(protocol:str = '', authprotos:str = '', extraparams:str = ''):
|
|
319
|
+
"""Returns user help regarding the credential url format"""
|
|
320
|
+
template = """
|
|
321
|
+
URL format:
|
|
322
|
+
|
|
323
|
+
protocol+authproto-secrettype://[domain]\\username:secret@[ip|hostname]:[port]/?param1=value1¶m2=value2
|
|
324
|
+
|
|
325
|
+
protocol: The protocol to use (see below)
|
|
326
|
+
%s
|
|
327
|
+
authproto (protocol dependent):
|
|
328
|
+
%s
|
|
329
|
+
username: The username to authenticate with
|
|
330
|
+
secret: The secret to authenticate with (depends on secrettype)
|
|
331
|
+
domain: The domain of the user
|
|
332
|
+
secrettype: The type of the secret (see below)
|
|
333
|
+
password/pw/pass: A plaintext password
|
|
334
|
+
pwb64: A base64 encoded password
|
|
335
|
+
pwprompt: Password will be prompted for on STDIN
|
|
336
|
+
pwhex: A hex encoded password
|
|
337
|
+
nt: NT hash
|
|
338
|
+
==== Kerberos only ====
|
|
339
|
+
rc4: RC4 key (Kerberos only)
|
|
340
|
+
aes: AES key (any size, Kerberos only)
|
|
341
|
+
aes128: AES128 key (Kerberos only)
|
|
342
|
+
aes256: AES256 key (Kerberos only)
|
|
343
|
+
ccache: ccache file name (only local directory)
|
|
344
|
+
ccachehex: A hex encoded ccache file
|
|
345
|
+
ccacheb64: A base64 encoded ccache file
|
|
346
|
+
keytab: keytab file name (only local directory)
|
|
347
|
+
keytabhex: A hex encoded keytab file
|
|
348
|
+
keytabb64: A base64 encoded keytab file
|
|
349
|
+
pfx: pfx file name (only local directory)
|
|
350
|
+
pfxhex: A hex encoded pfx file
|
|
351
|
+
pfxb64: A base64 encoded pfx file
|
|
352
|
+
pem: pem file name (only local directory)
|
|
353
|
+
pemhex: A hex encoded pem file
|
|
354
|
+
pemb64: A base64 encoded pem file
|
|
355
|
+
certstore: Use Windows certificate store (Windows only, Kerberos only)
|
|
356
|
+
kirbi: kirbi file name (only local directory)
|
|
357
|
+
kirbihex: A hex encoded kirbi file
|
|
358
|
+
kirbib64: A base64 encoded kirbi file
|
|
359
|
+
==== SSH Only ====
|
|
360
|
+
sshprivkey: ssh private key file name (only local directory)
|
|
361
|
+
sshprivkeystr: ssh private key file data in string format
|
|
362
|
+
sshprivkeyb64: A base64 encoded ssh private key file
|
|
363
|
+
|
|
364
|
+
Extra parameters are in the form of param=value. The following parameters are supported:
|
|
365
|
+
altname: Alternative name for certificate authentication
|
|
366
|
+
altdomain: Alternative domain for certificate authentication
|
|
367
|
+
etype: Supported encryption type to use (Kerberos only)
|
|
368
|
+
dc: The domain controller to use (Kerberos only)
|
|
369
|
+
dns: Don't use this.
|
|
370
|
+
%s
|
|
371
|
+
"""
|
|
372
|
+
return template % (protocol, authprotos, extraparams)
|
|
373
|
+
#add examples
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
from badauth.common.credentials.credssp import CREDSSPCredential
|
|
378
|
+
from badauth.common.credentials.kerberos import KerberosCredential
|
|
379
|
+
from badauth.common.credentials.ntlm import NTLMCredential
|
|
380
|
+
from badauth.common.credentials.spnego import SPNEGOCredential
|
|
381
|
+
from badauth.common.credentials.spnegoex import SPNEGOEXCredential
|
|
382
|
+
|
|
383
|
+
|
|
384
|
+
__all__ = [
|
|
385
|
+
'CREDSSPCredential',
|
|
386
|
+
'KerberosCredential',
|
|
387
|
+
'NTLMCredential',
|
|
388
|
+
'SPNEGOCredential',
|
|
389
|
+
'SPNEGOEXCredential',
|
|
390
|
+
]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
|
|
2
|
+
from typing import List
|
|
3
|
+
from badauth.common.credentials import UniCredential
|
|
4
|
+
from badauth.common.constants import asyauthSecret, asyauthProtocol, asyauthSubProtocol
|
|
5
|
+
from badauth.common.subprotocols import SubProtocol
|
|
6
|
+
from badauth.common.subprotocols import SubProtocolNative
|
|
7
|
+
from badauth.common.credentials.spnego import SPNEGOCredential
|
|
8
|
+
|
|
9
|
+
class CREDSSPCredential(UniCredential):
|
|
10
|
+
def __init__(self, credentials:List[UniCredential] = [], subprotocol:SubProtocol = SubProtocolNative()):
|
|
11
|
+
UniCredential.__init__(self, protocol = asyauthProtocol.CREDSSP, subprotocol=subprotocol)
|
|
12
|
+
self.credentials = credentials
|
|
13
|
+
|
|
14
|
+
def build_context(self, *args, **kwargs):
|
|
15
|
+
spnego_cred = SPNEGOCredential(self.credentials)
|
|
16
|
+
if self.subprotocol.type == asyauthSubProtocol.NATIVE:
|
|
17
|
+
from badauth.protocols.credssp.client.native import CredSSPClientNative
|
|
18
|
+
credssp_ctx = CredSSPClientNative(self)
|
|
19
|
+
credssp_ctx.auth_ctx = spnego_cred.build_context()
|
|
20
|
+
else:
|
|
21
|
+
raise Exception('Unsupported subprotocol "%s"' % self.subprotocol)
|
|
22
|
+
|
|
23
|
+
return credssp_ctx
|
|
24
|
+
|