from pyasn1.type import tag, univ, namedtype, namedval, constraint from pyasn1.codec.der import encoder, decoder __all__ = [ 'generateNegotiateSecurityBlob', 'generateAuthSecurityBlob', 'decodeChallengeSecurityBlob', 'decodeAuthResponseSecurityBlob' ] class UnsupportedSecurityProvider(Exception): pass class BadSecurityBlobError(Exception): pass def generateNegotiateSecurityBlob(ntlm_data): mech_token = univ.OctetString(ntlm_data).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)) mech_types = MechTypeList().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)) mech_types.setComponentByPosition(0, univ.ObjectIdentifier('1.3.6.1.4.1.311.2.2.10')) n = NegTokenInit().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0)) n.setComponentByName('mechTypes', mech_types) n.setComponentByName('mechToken', mech_token) nt = NegotiationToken() nt.setComponentByName('negTokenInit', n) ct = ContextToken() ct.setComponentByName('thisMech', univ.ObjectIdentifier('1.3.6.1.5.5.2')) ct.setComponentByName('innerContextToken', nt) return encoder.encode(ct) def generateAuthSecurityBlob(ntlm_data): response_token = univ.OctetString(ntlm_data).subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)) n = NegTokenTarg().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1)) n.setComponentByName('responseToken', response_token) nt = NegotiationToken() nt.setComponentByName('negTokenTarg', n) return encoder.encode(nt) def decodeChallengeSecurityBlob(data): try: d, _ = decoder.decode(data, asn1Spec = NegotiationToken()) nt = d.getComponentByName('negTokenTarg') token = nt.getComponentByName('responseToken') if not token: raise BadSecurityBlobError('NTLMSSP_CHALLENGE security blob does not contain responseToken field') provider_oid = nt.getComponentByName('supportedMech') if provider_oid and str(provider_oid) != '1.3.6.1.4.1.311.2.2.10': # This OID is defined in [MS-NLMP]: 1.9 raise UnsupportedSecurityProvider('Security provider "%s" is not supported by pysmb' % str(provider_oid)) result = nt.getComponentByName('negResult') return int(result), str(token) except Exception, ex: raise BadSecurityBlobError(str(ex)) def decodeAuthResponseSecurityBlob(data): try: d, _ = decoder.decode(data, asn1Spec = NegotiationToken()) nt = d.getComponentByName('negTokenTarg') result = nt.getComponentByName('negResult') return int(result) except Exception, ex: raise BadSecurityBlobError(str(ex)) # # GSS-API ASN.1 (RFC2478 section 3.2.1) # RESULT_ACCEPT_COMPLETED = 0 RESULT_ACCEPT_INCOMPLETE = 1 RESULT_REJECT = 2 class NegResultEnumerated(univ.Enumerated): namedValues = namedval.NamedValues( ( 'accept_completed', 0 ), ( 'accept_incomplete', 1 ), ( 'reject', 2 ) ) subtypeSpec = univ.Enumerated.subtypeSpec + constraint.SingleValueConstraint(0, 1, 2) class MechTypeList(univ.SequenceOf): componentType = univ.ObjectIdentifier() class ContextFlags(univ.BitString): namedValues = namedval.NamedValues( ( 'delegFlag', 0 ), ( 'mutualFlag', 1 ), ( 'replayFlag', 2 ), ( 'sequenceFlag', 3 ), ( 'anonFlag', 4 ), ( 'confFlag', 5 ), ( 'integFlag', 6 ) ) class NegTokenInit(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.OptionalNamedType('mechTypes', MechTypeList().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), namedtype.OptionalNamedType('reqFlags', ContextFlags().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))), namedtype.OptionalNamedType('mechToken', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))), namedtype.OptionalNamedType('mechListMIC', univ.OctetString().subtype(implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) ) class NegTokenTarg(univ.Sequence): componentType = namedtype.NamedTypes( namedtype.OptionalNamedType('negResult', NegResultEnumerated().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), namedtype.OptionalNamedType('supportedMech', univ.ObjectIdentifier().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))), namedtype.OptionalNamedType('responseToken', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 2))), namedtype.OptionalNamedType('mechListMIC', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 3))) ) class NegotiationToken(univ.Choice): componentType = namedtype.NamedTypes( namedtype.NamedType('negTokenInit', NegTokenInit().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 0))), namedtype.NamedType('negTokenTarg', NegTokenTarg().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))) ) class ContextToken(univ.Sequence): tagSet = univ.Sequence.tagSet.tagImplicitly(tag.Tag(tag.tagClassApplication, tag.tagFormatConstructed, 0)) componentType = namedtype.NamedTypes( namedtype.NamedType('thisMech', univ.ObjectIdentifier()), namedtype.NamedType('innerContextToken', NegotiationToken()) )