| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322 |
- {
- $Project$
- $Workfile$
- $Revision$
- $DateUTC$
- $Id$
- This file is part of the Indy (Internet Direct) project, and is offered
- under the dual-licensing agreement described on the Indy website.
- (http://www.indyproject.org/)
- Copyright:
- (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
- }
- {
- $Log$
- }
- {
- Rev 1.3 6/11/2004 9:33:58 AM DSiders
- Added "Do not Localize" comments.
- Rev 1.2 13.1.2004 ã. 17:26:06 DBondzhev
- Added Domain property
- Rev 1.1 4/12/2003 10:24:04 PM GGrieve
- Fix to Compile
- Rev 1.0 11/14/2002 02:13:50 PM JPMugaas
- }
- unit IdAuthenticationSSPI;
- {
- Implementation of the NTLM authentication with SSPI
- Author: Alex Brainman
- Copyright: (c) Chad Z. Hower and The Winshoes Working Group.
- }
- {$DEFINE SET_ENCRYPT_IN_FT_WITH_GETPROCADDRESS_FUDGE}
- interface
- {$i IdCompilerDefines.inc}
- uses
- IdGlobal,
- IdAuthentication,
- IdCoder,
- Windows,
- SysUtils,
- IdSSPI;
- const
- SEC_E_OK = 0;
- {$EXTERNALSYM SEC_E_OK}
- SEC_E_INSUFFICIENT_MEMORY = HRESULT($80090300);
- {$EXTERNALSYM SEC_E_INSUFFICIENT_MEMORY}
- SEC_E_INVALID_HANDLE = HRESULT($80090301);
- {$EXTERNALSYM SEC_E_INVALID_HANDLE}
- SEC_E_UNSUPPORTED_FUNCTION = HRESULT($80090302);
- {$EXTERNALSYM SEC_E_UNSUPPORTED_FUNCTION}
- SEC_E_TARGET_UNKNOWN = HRESULT($80090303);
- {$EXTERNALSYM SEC_E_TARGET_UNKNOWN}
- SEC_E_INTERNAL_ERROR = HRESULT($80090304);
- {$EXTERNALSYM SEC_E_INTERNAL_ERROR}
- SEC_E_SECPKG_NOT_FOUND = HRESULT($80090305);
- {$EXTERNALSYM SEC_E_SECPKG_NOT_FOUND}
- SEC_E_NOT_OWNER = HRESULT($80090306);
- {$EXTERNALSYM SEC_E_NOT_OWNER}
- SEC_E_CANNOT_INSTALL = HRESULT($80090307);
- {$EXTERNALSYM SEC_E_CANNOT_INSTALL}
- SEC_E_INVALID_TOKEN = HRESULT($80090308);
- {$EXTERNALSYM SEC_E_INVALID_TOKEN}
- SEC_E_CANNOT_PACK = HRESULT($80090309);
- {$EXTERNALSYM SEC_E_CANNOT_PACK}
- SEC_E_QOP_NOT_SUPPORTED = HRESULT($8009030A);
- {$EXTERNALSYM SEC_E_QOP_NOT_SUPPORTED}
- SEC_E_NO_IMPERSONATION = HRESULT($8009030B);
- {$EXTERNALSYM SEC_E_NO_IMPERSONATION}
- SEC_E_LOGON_DENIED = HRESULT($8009030C);
- {$EXTERNALSYM SEC_E_LOGON_DENIED}
- SEC_E_UNKNOWN_CREDENTIALS = HRESULT($8009030D);
- {$EXTERNALSYM SEC_E_UNKNOWN_CREDENTIALS}
- SEC_E_NO_CREDENTIALS = HRESULT($8009030E);
- {$EXTERNALSYM SEC_E_NO_CREDENTIALS}
- SEC_E_MESSAGE_ALTERED = HRESULT($8009030F);
- {$EXTERNALSYM SEC_E_MESSAGE_ALTERED}
- SEC_E_OUT_OF_SEQUENCE = HRESULT($80090310);
- {$EXTERNALSYM SEC_E_OUT_OF_SEQUENCE}
- SEC_E_NO_AUTHENTICATING_AUTHORITY = HRESULT($80090311);
- {$EXTERNALSYM SEC_E_NO_AUTHENTICATING_AUTHORITY}
- SEC_I_CONTINUE_NEEDED = HRESULT($00090312);
- {$EXTERNALSYM SEC_I_CONTINUE_NEEDED}
- SEC_I_COMPLETE_NEEDED = HRESULT($00090313);
- {$EXTERNALSYM SEC_I_COMPLETE_NEEDED}
- SEC_I_COMPLETE_AND_CONTINUE = HRESULT($00090314);
- {$EXTERNALSYM SEC_I_COMPLETE_AND_CONTINUE}
- SEC_I_LOCAL_LOGON = HRESULT($00090315);
- {$EXTERNALSYM SEC_I_LOCAL_LOGON}
- SEC_E_BAD_PKGID = HRESULT($80090316);
- {$EXTERNALSYM SEC_E_BAD_PKGID}
- SEC_E_CONTEXT_EXPIRED = HRESULT($80090317);
- {$EXTERNALSYM SEC_E_CONTEXT_EXPIRED}
- SEC_E_INCOMPLETE_MESSAGE = HRESULT($80090318);
- {$EXTERNALSYM SEC_E_INCOMPLETE_MESSAGE}
- SEC_E_INCOMPLETE_CREDENTIALS = HRESULT($80090320);
- {$EXTERNALSYM SEC_E_INCOMPLETE_CREDENTIALS}
- SEC_E_BUFFER_TOO_SMALL = HRESULT($80090321);
- {$EXTERNALSYM SEC_E_BUFFER_TOO_SMALL}
- SEC_I_INCOMPLETE_CREDENTIALS = HRESULT($00090320);
- {$EXTERNALSYM SEC_I_INCOMPLETE_CREDENTIALS}
- SEC_I_RENEGOTIATE = HRESULT($00090321);
- {$EXTERNALSYM SEC_I_RENEGOTIATE}
- SEC_E_WRONG_PRINCIPAL = HRESULT($80090322);
- {$EXTERNALSYM SEC_E_WRONG_PRINCIPAL}
- SEC_I_NO_LSA_CONTEXT = HRESULT($00090323);
- {$EXTERNALSYM SEC_I_NO_LSA_CONTEXT}
- SEC_E_TIME_SKEW = HRESULT($80090324);
- {$EXTERNALSYM SEC_E_TIME_SKEW}
- SEC_E_UNTRUSTED_ROOT = HRESULT($80090325);
- {$EXTERNALSYM SEC_E_UNTRUSTED_ROOT}
- SEC_E_ILLEGAL_MESSAGE = HRESULT($80090326);
- {$EXTERNALSYM SEC_E_ILLEGAL_MESSAGE}
- SEC_E_CERT_UNKNOWN = HRESULT($80090327);
- {$EXTERNALSYM SEC_E_CERT_UNKNOWN}
- SEC_E_CERT_EXPIRED = HRESULT($80090328);
- {$EXTERNALSYM SEC_E_CERT_EXPIRED}
- SEC_E_ENCRYPT_FAILURE = HRESULT($80090329);
- {$EXTERNALSYM SEC_E_ENCRYPT_FAILURE}
- SEC_E_DECRYPT_FAILURE = HRESULT($80090330);
- {$EXTERNALSYM SEC_E_DECRYPT_FAILURE}
- SEC_E_ALGORITHM_MISMATCH = HRESULT($80090331);
- {$EXTERNALSYM SEC_E_ALGORITHM_MISMATCH}
- SEC_E_SECURITY_QOS_FAILED = HRESULT($80090332);
- {$EXTERNALSYM SEC_E_SECURITY_QOS_FAILED}
-
- SEC_E_UNFINISHED_CONTEXT_DELETED = HRESULT($80090333);
- {$EXTERNALSYM SEC_E_UNFINISHED_CONTEXT_DELETED}
- SEC_E_NO_TGT_REPLY = HRESULT($80090334);
- {$EXTERNALSYM SEC_E_NO_TGT_REPLY}
- SEC_E_NO_IP_ADDRESSES = HRESULT($80090335);
- {$EXTERNALSYM SEC_E_NO_IP_ADDRESSES}
- SEC_E_WRONG_CREDENTIAL_HANDLE = HRESULT($80090336);
- {$EXTERNALSYM SEC_E_WRONG_CREDENTIAL_HANDLE}
- SEC_E_CRYPTO_SYSTEM_INVALID = HRESULT($80090337);
- {$EXTERNALSYM SEC_E_CRYPTO_SYSTEM_INVALID}
- SEC_E_MAX_REFERRALS_EXCEEDED = HRESULT($80090338);
- {$EXTERNALSYM SEC_E_MAX_REFERRALS_EXCEEDED}
- SEC_E_MUST_BE_KDC = HRESULT($80090339);
- {$EXTERNALSYM SEC_E_MUST_BE_KDC}
- SEC_E_STRONG_CRYPTO_NOT_SUPPORTED = HRESULT($8009033A);
- {$EXTERNALSYM SEC_E_STRONG_CRYPTO_NOT_SUPPORTED}
- SEC_E_TOO_MANY_PRINCIPALS = HRESULT($8009033B);
- {$EXTERNALSYM SEC_E_TOO_MANY_PRINCIPALS}
- SEC_E_NO_PA_DATA = HRESULT($8009033C);
- {$EXTERNALSYM SEC_E_NO_PA_DATA}
- SEC_E_PKINIT_NAME_MISMATCH = HRESULT($8009033D);
- {$EXTERNALSYM SEC_E_PKINIT_NAME_MISMATCH}
- SEC_E_SMARTCARD_LOGON_REQUIRED = HRESULT($8009033E);
- {$EXTERNALSYM SEC_E_SMARTCARD_LOGON_REQUIRED}
- SEC_E_SHUTDOWN_IN_PROGRESS = HRESULT($8009033F);
- {$EXTERNALSYM SEC_E_SHUTDOWN_IN_PROGRESS}
- SEC_E_KDC_INVALID_REQUEST = HRESULT($80090340);
- {$EXTERNALSYM SEC_E_KDC_INVALID_REQUEST}
- SEC_E_KDC_UNABLE_TO_REFER = HRESULT($80090341);
- {$EXTERNALSYM SEC_E_KDC_UNABLE_TO_REFER}
- SEC_E_KDC_UNKNOWN_ETYPE = HRESULT($80090342);
- {$EXTERNALSYM SEC_E_KDC_UNKNOWN_ETYPE}
- SEC_E_UNSUPPORTED_PREAUTH = HRESULT($80090343);
- {$EXTERNALSYM SEC_E_UNSUPPORTED_PREAUTH}
- SEC_E_DELEGATION_REQUIRED = HRESULT($80090345);
- {$EXTERNALSYM SEC_E_DELEGATION_REQUIRED}
- SEC_E_BAD_BINDINGS = HRESULT($80090346);
- {$EXTERNALSYM SEC_E_BAD_BINDINGS}
- SEC_E_MULTIPLE_ACCOUNTS = HRESULT($80090347);
- {$EXTERNALSYM SEC_E_MULTIPLE_ACCOUNTS}
- SEC_E_NO_KERB_KEY = HRESULT($80090348);
- {$EXTERNALSYM SEC_E_NO_KERB_KEY}
- SEC_E_CERT_WRONG_USAGE = HRESULT($80090349);
- {$EXTERNALSYM SEC_E_CERT_WRONG_USAGE}
- SEC_E_DOWNGRADE_DETECTED = HRESULT($80090350);
- {$EXTERNALSYM SEC_E_DOWNGRADE_DETECTED}
- SEC_E_SMARTCARD_CERT_REVOKED = HRESULT($80090351);
- {$EXTERNALSYM SEC_E_SMARTCARD_CERT_REVOKED}
- SEC_E_ISSUING_CA_UNTRUSTED = HRESULT($80090352);
- {$EXTERNALSYM SEC_E_ISSUING_CA_UNTRUSTED}
- SEC_E_REVOCATION_OFFLINE_C = HRESULT($80090353);
- {$EXTERNALSYM SEC_E_REVOCATION_OFFLINE_C}
- SEC_E_PKINIT_CLIENT_FAILURE = HRESULT($80090354);
- {$EXTERNALSYM SEC_E_PKINIT_CLIENT_FAILURE}
- SEC_E_SMARTCARD_CERT_EXPIRED = HRESULT($80090355);
- {$EXTERNALSYM SEC_E_SMARTCARD_CERT_EXPIRED}
- SEC_E_NO_S4U_PROT_SUPPORT = HRESULT($80090356);
- {$EXTERNALSYM SEC_E_NO_S4U_PROT_SUPPORT}
- SEC_E_CROSSREALM_DELEGATION_FAILURE = HRESULT($80090357);
- {$EXTERNALSYM SEC_E_CROSSREALM_DELEGATION_FAILURE}
- SEC_E_REVOCATION_OFFLINE_KDC = HRESULT($80090358);
- {$EXTERNALSYM SEC_E_REVOCATION_OFFLINE_KDC}
- SEC_E_ISSUING_CA_UNTRUSTED_KDC = HRESULT($80090359);
- {$EXTERNALSYM SEC_E_ISSUING_CA_UNTRUSTED_KDC}
- SEC_E_KDC_CERT_EXPIRED = HRESULT($8009035A);
- {$EXTERNALSYM SEC_E_KDC_CERT_EXPIRED}
- SEC_E_KDC_CERT_REVOKED = HRESULT($8009035B);
- {$EXTERNALSYM SEC_E_KDC_CERT_REVOKED}
- SEC_I_SIGNATURE_NEEDED = HRESULT($0009035C);
- {$EXTERNALSYM SEC_I_SIGNATURE_NEEDED}
- SEC_E_INVALID_PARAMETER = HRESULT($8009035D);
- {$EXTERNALSYM SEC_E_INVALID_PARAMETER}
- SEC_E_DELEGATION_POLICY = HRESULT($8009035E);
- {$EXTERNALSYM SEC_E_DELEGATION_POLICY}
- SEC_E_POLICY_NLTM_ONLY = HRESULT($8009035F);
- {$EXTERNALSYM SEC_E_POLICY_NLTM_ONLY}
- SEC_I_NO_RENEGOTIATION = HRESULT($00090360);
- {$EXTERNALSYM SEC_I_NO_RENEGOTIATION}
- SEC_E_NO_CONTEXT = HRESULT($80090361);
- {$EXTERNALSYM SEC_E_NO_CONTEXT}
- SEC_E_PKU2U_CERT_FAILURE = HRESULT($80090362);
- {$EXTERNALSYM SEC_E_PKU2U_CERT_FAILURE}
- SEC_E_MUTUAL_AUTH_FAILED = HRESULT($80090363);
- {$EXTERNALSYM SEC_E_MUTUAL_AUTH_FAILED}
- type
- ESSPIException = class(Exception)
- public
- // Params must be in this order to avoid conflict with CreateHelp
- // constructor in CBuilder as CB does not differentiate constructors
- // by name as Delphi does
- constructor CreateError(const AErrorNo: Integer; const AFailedFuncName: string);
- //
- class function GetErrorMessageByNo(AErrorNo: UInt32): string;
- end;
- ESSPIInterfaceInitFailed = class(ESSPIException);
- { TSSPIInterface }
- TSSPIInterface = class(TObject)
- private
- fLoadPending, fIsAvailable: Boolean;
- fPFunctionTable: PSecurityFunctionTable;
- fDLLHandle: TIdLibHandle;
- procedure ReleaseFunctionTable;
- procedure CheckAvailable;
- function GetFunctionTable: SecurityFunctionTable;
- public
- class procedure RaiseIfError(aStatus: SECURITY_STATUS; const aFunctionName: string);
- function IsAvailable: Boolean;
- property FunctionTable: SecurityFunctionTable read GetFunctionTable;
- public
- constructor Create;
- destructor Destroy; override;
- end;
- { TSSPIPackages }
- TSSPIPackage = class(TObject)
- private
- fPSecPkginfo: PSecPkgInfo;
- function GetPSecPkgInfo: PSecPkgInfo;
- function GetMaxToken: ULONG;
- function GetName: {$IFDEF SSPI_UNICODE}TIdUnicodeString{$ELSE}AnsiString{$ENDIF};
- public
- property MaxToken: ULONG read GetMaxToken;
- property Name: {$IFDEF SSPI_UNICODE}TIdUnicodeString{$ELSE}AnsiString{$ENDIF} read GetName;
- public
- constructor Create(aPSecPkginfo: PSecPkgInfo);
- end;
- TCustomSSPIPackage = class(TSSPIPackage)
- private
- fInfo: PSecPkgInfo;
- public
- constructor Create(const aPkgName: {$IFDEF SSPI_UNICODE}TIdUnicodeString{$ELSE}AnsiString{$ENDIF});
- destructor Destroy; override;
- end;
- TSSPINTLMPackage = class(TCustomSSPIPackage)
- public
- constructor Create;
- end;
- { TSSPICredentials }
- TSSPICredentialsUse = (scuInBound, scuOutBound, scuBoth);
- TSSPICredentials = class(TObject)
- private
- fPackage: TSSPIPackage;
- fHandle: CredHandle;
- fUse: TSSPICredentialsUse;
- fAcquired: Boolean;
- fExpiry: TimeStamp;
- function GetHandle: PCredHandle;
- procedure SetUse(aValue: TSSPICredentialsUse);
- protected
- procedure CheckAcquired;
- procedure CheckNotAcquired;
- procedure DoAcquire(pszPrincipal: {$IFDEF SSPI_UNICODE}PSEC_WCHAR{$ELSE}PSEC_CHAR{$ENDIF}; pvLogonId, pAuthData: PVOID);
- procedure DoRelease; virtual;
- public
- procedure Release;
- property Package: TSSPIPackage read fPackage;
- property Handle: PCredHandle read GetHandle;
- property Use: TSSPICredentialsUse read fUse write SetUse;
- property Acquired: Boolean read fAcquired;
- public
- constructor Create(aPackage: TSSPIPackage);
- destructor Destroy; override;
- end;
- { TSSPIWinNTCredentials }
- TSSPIWinNTCredentials = class(TSSPICredentials)
- protected
- public
- procedure Acquire(aUse: TSSPICredentialsUse); overload;
- procedure Acquire(aUse: TSSPICredentialsUse;
- const aDomain, aUserName, aPassword: {$IFDEF SSPI_UNICODE}TIdUnicodeString{$ELSE}AnsiString{$ENDIF}); overload;
- end;
- { TSSPIContext }
- TSSPIContext = class(TObject)
- private
- fCredentials: TSSPICredentials;
- fHandle: CtxtHandle;
- fHasHandle: Boolean;
- fExpiry: TimeStamp;
- function GetHandle: PCtxtHandle;
- function GetExpiry: TimeStamp;
- procedure UpdateHasContextAndCheckForError(
- const aFuncResult: SECURITY_STATUS; const aFuncName: string;
- const aErrorsToIgnore: array of SECURITY_STATUS);
- protected
- procedure CheckHasHandle;
- procedure CheckCredentials;
- function DoInitialize(const aTokenSourceName: {$IFDEF SSPI_UNICODE}TIdUnicodeString{$ELSE}AnsiString{$ENDIF};
- var aIn, aOut: SecBufferDesc;
- const errorsToIgnore: array of SECURITY_STATUS): SECURITY_STATUS;
- procedure DoRelease; virtual;
- function GetRequestedFlags: ULONG; virtual; abstract;
- procedure SetEstablishedFlags(aFlags: ULONG); virtual; abstract;
- function GetAuthenticated: Boolean; virtual; abstract;
- property HasHandle: Boolean read fHasHandle;
- public
- procedure Release;
- property Credentials: TSSPICredentials read fCredentials;
- property Handle: PCtxtHandle read GetHandle;
- property Authenticated: Boolean read GetAuthenticated;
- property Expiry: TimeStamp read GetExpiry;
- public
- constructor Create(aCredentials: TSSPICredentials);
- destructor Destroy; override;
- end;
- { TSSPIConnectionContext }
- TCustomSSPIConnectionContext = class(TSSPIContext)
- private
- fStatus: SECURITY_STATUS;
- fOutBuffDesc, fInBuffDesc: SecBufferDesc;
- fInBuff: SecBuffer;
- protected
- procedure DoRelease; override;
- function GetAuthenticated: Boolean; override;
- function DoUpdateAndGenerateReply(var aIn, aOut: SecBufferDesc;
- const aErrorsToIgnore: array of SECURITY_STATUS
- ): SECURITY_STATUS; virtual; abstract;
- public
- constructor Create(ACredentials: TSSPICredentials);
- function UpdateAndGenerateReply(
- const aFromPeerToken: TIdBytes; var aToPeerToken: TIdBytes): Boolean;
- end;
- TSSPIClientConnectionContext = class(TCustomSSPIConnectionContext)
- private
- fTargetName: string;
- fReqReguested, fReqEstablished: ULONG;
- protected
- function GetRequestedFlags: ULONG; override;
- procedure SetEstablishedFlags(aFlags: ULONG); override;
- function DoUpdateAndGenerateReply(var aIn, aOut: SecBufferDesc;
- const aErrorsToIgnore: array of SECURITY_STATUS
- ): SECURITY_STATUS; override;
- public
- function GenerateInitialChallenge(const aTargetName: string;
- var aToPeerToken: TIdBytes): Boolean;
- public
- constructor Create(aCredentials: TSSPICredentials);
- end;
- TIndySSPINTLMClient = class(TObject)
- protected
- fNTLMPackage: TSSPINTLMPackage;
- fCredentials: TSSPIWinNTCredentials;
- fContext: TSSPIClientConnectionContext;
- public
- procedure SetCredentials(const aDomain, aUserName, aPassword: string);
- procedure SetCredentialsAsCurrentUser;
- function InitAndBuildType1Message: TIdBytes;
- function UpdateAndBuildType3Message(const aServerType2Message: TIdBytes): TIdBytes;
- public
- constructor Create;
- destructor Destroy; override;
- end;
- TIdSSPINTLMAuthentication = class(TIdAuthentication)
- protected
- FNTLMInfo: string;
- FSSPIClient: TIndySSPINTLMClient;
- procedure SetDomain(const Value: String);
- function GetDomain: String;
- procedure SetUserName(const Value: String); override;
- function GetSteps: Integer; override;
- function DoNext: TIdAuthWhatsNext; override;
- public
- constructor Create; override;
- destructor Destroy; override;
- function Authentication: string; override;
- function KeepAlive: Boolean; override;
- property Domain: String read GetDomain write SetDomain;
- end;
- // RLebeau 4/17/10: this forces C++Builder to link to this unit so
- // RegisterAuthenticationMethod can be called correctly at program startup...
- {$IFDEF HAS_DIRECTIVE_HPPEMIT_LINKUNIT}
- {$HPPEMIT LINKUNIT}
- {$ELSE}
- {$HPPEMIT '#pragma link "IdAuthenticationSSPI"'}
- {$ENDIF}
- implementation
- uses
- IdGlobalProtocols,
- IdCoderMIME,
- IdResourceStringsSSPI,
- IdHeaderList;
- var
- gSSPIInterface: TSSPIInterface = nil;
- gAuthRegistered: Boolean = False;
- { ESSPIException }
- class function ESSPIException.GetErrorMessageByNo(aErrorNo: UInt32): string;
- begin
- case HRESULT(aErrorNo) of
- SEC_E_OK:
- Result := RSHTTPSSPISuccess;
- SEC_E_INSUFFICIENT_MEMORY:
- Result := RSHTTPSSPINotEnoughMem;
- SEC_E_INVALID_HANDLE:
- Result := RSHTTPSSPIInvalidHandle;
- SEC_E_UNSUPPORTED_FUNCTION:
- Result := RSHTTPSSPIFuncNotSupported;
- SEC_E_TARGET_UNKNOWN:
- Result := RSHTTPSSPIUnknownTarget;
- SEC_E_INTERNAL_ERROR:
- Result := RSHTTPSSPIInternalError;
- SEC_E_SECPKG_NOT_FOUND:
- Result := RSHTTPSSPISecPackageNotFound;
- SEC_E_NOT_OWNER:
- Result := RSHTTPSSPINotOwner;
- SEC_E_CANNOT_INSTALL:
- Result := RSHTTPSSPIPackageCannotBeInstalled;
- SEC_E_INVALID_TOKEN:
- Result := RSHTTPSSPIInvalidToken;
- SEC_E_CANNOT_PACK:
- Result := RSHTTPSSPICannotPack;
- SEC_E_QOP_NOT_SUPPORTED:
- Result := RSHTTPSSPIQOPNotSupported;
- SEC_E_NO_IMPERSONATION:
- Result := RSHTTPSSPINoImpersonation;
- SEC_E_LOGON_DENIED:
- Result := RSHTTPSSPILoginDenied;
- SEC_E_UNKNOWN_CREDENTIALS:
- Result := RSHTTPSSPIUnknownCredentials;
- SEC_E_NO_CREDENTIALS:
- Result := RSHTTPSSPINoCredentials;
- SEC_E_MESSAGE_ALTERED:
- Result := RSHTTPSSPIMessageAltered;
- SEC_E_OUT_OF_SEQUENCE:
- Result := RSHTTPSSPIOutOfSequence;
- SEC_E_NO_AUTHENTICATING_AUTHORITY:
- Result := RSHTTPSSPINoAuthAuthority;
- SEC_I_CONTINUE_NEEDED:
- Result := RSHTTPSSPIContinueNeeded;
- SEC_I_COMPLETE_NEEDED:
- Result := RSHTTPSSPICompleteNeeded;
- SEC_I_COMPLETE_AND_CONTINUE:
- Result :=RSHTTPSSPICompleteContinueNeeded;
- SEC_I_LOCAL_LOGON:
- Result := RSHTTPSSPILocalLogin;
- SEC_E_BAD_PKGID:
- Result := RSHTTPSSPIBadPackageID;
- SEC_E_CONTEXT_EXPIRED:
- Result := RSHTTPSSPIContextExpired;
- SEC_E_INCOMPLETE_MESSAGE:
- Result := RSHTTPSSPIIncompleteMessage;
- SEC_E_INCOMPLETE_CREDENTIALS:
- Result := RSHTTPSSPIIncompleteCredentialNotInit;
- SEC_E_BUFFER_TOO_SMALL:
- Result := RSHTTPSSPIBufferTooSmall;
- SEC_I_INCOMPLETE_CREDENTIALS:
- Result := RSHTTPSSPIIncompleteCredentialsInit;
- SEC_I_RENEGOTIATE:
- Result := RSHTTPSSPIRengotiate;
- SEC_E_WRONG_PRINCIPAL:
- Result := RSHTTPSSPIWrongPrincipal;
- SEC_I_NO_LSA_CONTEXT:
- Result := RSHTTPSSPINoLSACode;
- SEC_E_TIME_SKEW:
- Result := RSHTTPSSPITimeScew;
- SEC_E_UNTRUSTED_ROOT:
- Result := RSHTTPSSPIUntrustedRoot;
- SEC_E_ILLEGAL_MESSAGE:
- Result := RSHTTPSSPIIllegalMessage;
- SEC_E_CERT_UNKNOWN:
- Result := RSHTTPSSPICertUnknown;
- SEC_E_CERT_EXPIRED:
- Result := RSHTTPSSPICertExpired;
- SEC_E_ENCRYPT_FAILURE:
- Result := RSHTTPSSPIEncryptionFailure;
- SEC_E_DECRYPT_FAILURE:
- Result := RSHTTPSSPIDecryptionFailure;
- SEC_E_ALGORITHM_MISMATCH:
- Result := RSHTTPSSPIAlgorithmMismatch;
- SEC_E_SECURITY_QOS_FAILED:
- Result := RSHTTPSSPISecurityQOSFailure;
- SEC_E_UNFINISHED_CONTEXT_DELETED :
- Result := RSHTTPSSPISecCtxWasDelBeforeUpdated;
- SEC_E_NO_TGT_REPLY :
- Result := RSHTTPSSPIClientNoTGTReply;
- SEC_E_NO_IP_ADDRESSES :
- Result := RSHTTPSSPILocalNoIPAddr;
- SEC_E_WRONG_CREDENTIAL_HANDLE :
- Result := RSHTTPSSPIWrongCredHandle;
- SEC_E_CRYPTO_SYSTEM_INVALID :
- Result := RSHTTPSSPICryptoSysInvalid;
- SEC_E_MAX_REFERRALS_EXCEEDED :
- Result := RSHTTPSSPIMaxTicketRef;
- SEC_E_MUST_BE_KDC :
- Result := RSHTTPSSPIMustBeKDC;
- SEC_E_STRONG_CRYPTO_NOT_SUPPORTED :
- Result := RSHTTPSSPIStrongCryptoNotSupported;
- SEC_E_TOO_MANY_PRINCIPALS :
- Result := RSHTTPSSPIKDCReplyTooManyPrincipals;
- SEC_E_NO_PA_DATA :
- Result := RSHTTPSSPINoPAData;
- SEC_E_PKINIT_NAME_MISMATCH :
- Result := RSHTTPSSPIPKInitNameMismatch;
- SEC_E_SMARTCARD_LOGON_REQUIRED :
- Result := RSHTTPSSPISmartcardLogonReq;
- SEC_E_SHUTDOWN_IN_PROGRESS :
- Result := RSHTTPSSPISysShutdownInProg;
- SEC_E_KDC_INVALID_REQUEST :
- Result := RSHTTPSSPIKDCInvalidRequest;
- SEC_E_KDC_UNABLE_TO_REFER :
- Result := RSHTTPSSPIKDCUnableToRefer;
- SEC_E_KDC_UNKNOWN_ETYPE :
- Result := RSHTTPSSPIKDCETypeUnknown;
- SEC_E_UNSUPPORTED_PREAUTH :
- Result := RSHTTPSSPIUnsupPreauth;
- SEC_E_DELEGATION_REQUIRED :
- Result := RSHTTPSSPIDeligationReq;
- SEC_E_BAD_BINDINGS :
- Result := RSHTTPSSPIBadBindings;
- SEC_E_MULTIPLE_ACCOUNTS :
- Result := RSHTTPSSPIMultipleAccounts;
- SEC_E_NO_KERB_KEY :
- Result := RSHTTPSSPINoKerbKey;
- SEC_E_CERT_WRONG_USAGE :
- Result := RSHTTPSSPICertWrongUsage;
- SEC_E_DOWNGRADE_DETECTED :
- Result := RSHTTPSSPIDowngradeDetected;
- SEC_E_SMARTCARD_CERT_REVOKED :
- Result := RSHTTPSSPISmartcardCertRevoked;
- SEC_E_ISSUING_CA_UNTRUSTED :
- Result := RSHTTPSSPIIssuingCAUntrusted;
- SEC_E_REVOCATION_OFFLINE_C :
- Result := RSHTTPSSPIRevocationOffline;
- SEC_E_PKINIT_CLIENT_FAILURE :
- Result := RSHTTPSSPIPKInitClientFailure;
- SEC_E_SMARTCARD_CERT_EXPIRED :
- Result := RSHTTPSSPISmartcardExpired;
- SEC_E_NO_S4U_PROT_SUPPORT :
- Result := RSHTTPSSPINoS4UProtSupport;
- SEC_E_CROSSREALM_DELEGATION_FAILURE :
- Result := RSHTTPSSPICrossRealmDeligationFailure;
- SEC_E_REVOCATION_OFFLINE_KDC :
- Result := RSHTTPSSPIRevocationOfflineKDC;
- SEC_E_ISSUING_CA_UNTRUSTED_KDC :
- Result := RSHTTPSSPICAUntrustedKDC;
- SEC_E_KDC_CERT_EXPIRED :
- Result := RSHTTPSSPIKDCCertExpired;
- SEC_E_KDC_CERT_REVOKED :
- Result := RSHTTPSSPIKDCCertRevoked;
- SEC_I_SIGNATURE_NEEDED :
- Result := RSHTTPSSPISignatureNeeded;
- SEC_E_INVALID_PARAMETER :
- Result := RSHTTPSSPIInvalidParameter;
- SEC_E_DELEGATION_POLICY :
- Result := RSHTTPSSPIDeligationPolicy;
- SEC_E_POLICY_NLTM_ONLY :
- Result := RSHTTPSSPIPolicyNTLMOnly;
- SEC_I_NO_RENEGOTIATION :
- Result := RSHTTPSSPINoRenegotiation;
- SEC_E_NO_CONTEXT :
- Result := RSHTTPSSPINoContext;
- SEC_E_PKU2U_CERT_FAILURE :
- Result := RSHTTPSSPIPKU2UCertFailure;
- SEC_E_MUTUAL_AUTH_FAILED :
- Result := RSHTTPSSPIMutualAuthFailed;
- else
- Result := RSHTTPSSPIUnknwonError;
- end;
- end;
- constructor ESSPIException.CreateError(const AErrorNo: Integer; const AFailedFuncName: string);
- begin
- if AErrorNo = SEC_E_OK then begin
- inherited Create(AFailedFuncName);
- end else begin
- inherited CreateFmt(RSHTTPSSPIErrorMsg,
- [AFailedFuncName, AErrorNo, AErrorNo, GetErrorMessageByNo(AErrorNo)]);
- end;
- end;
- { TSSPIInterface }
- procedure TSSPIInterface.ReleaseFunctionTable;
- begin
- if fPFunctionTable <> nil then begin
- fPFunctionTable := nil;
- end;
- end;
- procedure TSSPIInterface.CheckAvailable;
- begin
- if not IsAvailable then begin
- raise ESSPIInterfaceInitFailed.Create(RSHTTPSSPIInterfaceInitFailed);
- end;
- end;
- function TSSPIInterface.GetFunctionTable: SecurityFunctionTable;
- begin
- CheckAvailable;
- Result := fPFunctionTable^;
- end;
- class procedure TSSPIInterface.RaiseIfError(aStatus: SECURITY_STATUS;
- const aFunctionName: string);
- begin
- if not SEC_SUCCESS(aStatus) then begin
- raise ESSPIException.CreateError(aStatus, aFunctionName);
- end;
- end;
- function TSSPIInterface.IsAvailable: Boolean;
- procedure LoadDLL;
- const
- SECURITY_DLL_NT = 'security.dll'; {Do not translate}
- SECURITY_DLL_95 = 'secur32.dll'; {Do not translate}
- ENCRYPT_MESSAGE = 'EncryptMessage'; {Do not translate}
- DECRYPT_MESSAGE = 'DecryptMessage'; {Do not translate}
- var
- dllName: string;
- entrypoint: INIT_SECURITY_INTERFACE;
- begin
- fIsAvailable := False;
- if IndyWindowsPlatform = VER_PLATFORM_WIN32_WINDOWS then
- { Windows95 SSPI dll }
- dllName := SECURITY_DLL_95
- else
- { WindowsNT & Windows2000 SSPI dll }
- dllName := SECURITY_DLL_NT;
- { load SSPI dll }
- //In Windows, you should use SafeLoadLibrary instead of the LoadLibrary API
- //call because LoadLibrary messes with the FPU control word.
- fDLLHandle := SafeLoadLibrary(dllName);
- if fDLLHandle <> IdNilHandle then begin
- { get InitSecurityInterface entry point
- and call it to fetch SPPI function table}
- entrypoint := LoadLibFunction(fDLLHandle, SECURITY_ENTRYPOINT);
- fPFunctionTable := entrypoint();
- { let's see what SSPI functions are available
- and if we can continue on with the set }
- fIsAvailable :=
- Assigned({$IFDEF SSPI_UNICODE}fPFunctionTable^.QuerySecurityPackageInfoW{$ELSE}fPFunctionTable^.QuerySecurityPackageInfoA{$ENDIF}) and
- Assigned(fPFunctionTable^.FreeContextBuffer) and
- Assigned(fPFunctionTable^.DeleteSecurityContext) and
- Assigned(fPFunctionTable^.FreeCredentialsHandle) and
- Assigned({$IFDEF SSPI_UNICODE}fPFunctionTable^.AcquireCredentialsHandleW{$ELSE}fPFunctionTable^.AcquireCredentialsHandleA{$ENDIF}) and
- Assigned({$IFDEF SSPI_UNICODE}fPFunctionTable^.InitializeSecurityContextW{$ELSE}fPFunctionTable^.InitializeSecurityContextA{$ENDIF}) and
- Assigned(fPFunctionTable^.AcceptSecurityContext) and
- Assigned(fPFunctionTable^.ImpersonateSecurityContext) and
- Assigned(fPFunctionTable^.RevertSecurityContext) and
- Assigned({$IFDEF SSPI_UNICODE}fPFunctionTable^.QueryContextAttributesW{$ELSE}fPFunctionTable^.QueryContextAttributesA{$ENDIF}) and
- Assigned(fPFunctionTable^.MakeSignature) and
- Assigned(fPFunctionTable^.VerifySignature);
- {$IFDEF SET_ENCRYPT_IN_FT_WITH_GETPROCADDRESS_FUDGE}
- { fudge for Encrypt/DecryptMessage }
- if not Assigned(fPFunctionTable^.EncryptMessage) then begin
- fPFunctionTable^.EncryptMessage := LoadLibFunction(fDLLHandle, ENCRYPT_MESSAGE);
- end;
- if not Assigned(fPFunctionTable^.DecryptMessage) then begin
- fPFunctionTable^.DecryptMessage := LoadLibFunction(fDLLHandle, DECRYPT_MESSAGE);
- end;
- {$ENDIF}
- end;
- end;
- begin
- if not fIsAvailable then begin
- if fLoadPending then begin
- ReleaseFunctionTable;
- LoadDLL;
- fLoadPending := False;
- end;
- end;
- Result := fIsAvailable;
- end;
- constructor TSSPIInterface.Create;
- begin
- inherited Create;
- fLoadPending := True;
- fIsAvailable := False;
- fPFunctionTable := nil;
- end;
- destructor TSSPIInterface.Destroy;
- begin
- ReleaseFunctionTable;
- if fDLLHandle <> IdNilHandle then begin
- FreeLibrary(fDLLHandle);
- fDLLHandle := IdNilHandle;
- end;
- inherited Destroy;
- end;
- { TSSPIPackage }
- constructor TSSPIPackage.Create(aPSecPkginfo: PSecPkgInfo);
- begin
- inherited Create;
- fPSecPkginfo := aPSecPkginfo;
- end;
- function TSSPIPackage.GetPSecPkgInfo: PSecPkgInfo;
- begin
- if not Assigned(fPSecPkginfo) then begin
- raise ESSPIException.Create(RSHTTPSSPINoPkgInfoSpecified);
- end;
- Result := fPSecPkginfo;
- end;
- function TSSPIPackage.GetMaxToken: ULONG;
- begin
- Result := GetPSecPkgInfo^.cbMaxToken;
- end;
- function TSSPIPackage.GetName: {$IFDEF SSPI_UNICODE}TIdUnicodeString{$ELSE}AnsiString{$ENDIF};
- begin
- Result := GetPSecPkgInfo^.Name;
- end;
- { TCustomSSPIPackage }
- constructor TCustomSSPIPackage.Create(const aPkgName: {$IFDEF SSPI_UNICODE}TIdUnicodeString{$ELSE}AnsiString{$ENDIF});
- begin
- gSSPIInterface.RaiseIfError(
- {$IFDEF SSPI_UNICODE}
- gSSPIInterface.FunctionTable.QuerySecurityPackageInfoW(PWideChar(aPkgName), @fInfo),
- 'QuerySecurityPackageInfoW' {Do not translate}
- {$ELSE}
- gSSPIInterface.FunctionTable.QuerySecurityPackageInfoA(PAnsiChar(aPkgName), @fInfo),
- 'QuerySecurityPackageInfoA' {Do not translate}
- {$ENDIF}
- );
- inherited Create(fInfo);
- end;
- destructor TCustomSSPIPackage.Destroy;
- begin
- if fInfo <> nil then begin
- gSSPIInterface.RaiseIfError(
- gSSPIInterface.FunctionTable.FreeContextBuffer(fInfo), 'FreeContextBuffer'); {Do not localize}
- end;
- inherited Destroy;
- end;
- { TSSPINTLMPackage }
- constructor TSSPINTLMPackage.Create;
- begin
- inherited Create(NTLMSP_NAME);
- end;
- { TSSPICredentials }
- constructor TSSPICredentials.Create(aPackage: TSSPIPackage);
- begin
- inherited Create;
- fPackage := aPackage;
- fUse := scuOutBound;
- fAcquired := False;
- end;
- procedure TSSPICredentials.CheckAcquired;
- begin
- if not fAcquired then begin
- raise ESSPIException.Create(RSHTTPSSPINoCredentialHandle);
- end;
- end;
- procedure TSSPICredentials.CheckNotAcquired;
- begin
- if fAcquired then begin
- raise ESSPIException.Create(RSHTTPSSPICanNotChangeCredentials);
- end;
- end;
- procedure TSSPICredentials.DoAcquire
- (pszPrincipal: {$IFDEF SSPI_UNICODE}PSEC_WCHAR{$ELSE}PSEC_CHAR{$ENDIF}; pvLogonId, pAuthData: PVOID);
- var
- cu: ULONG;
- begin
- Release;
- case Use of
- scuInBound:
- cu := SECPKG_CRED_INBOUND;
- scuOutBound:
- cu := SECPKG_CRED_OUTBOUND;
- scuBoth:
- cu := SECPKG_CRED_BOTH;
- else
- raise ESSPIException.Create(RSHTTPSSPIUnknwonCredentialUse);
- end;
- gSSPIInterface.RaiseIfError(
- gSSPIInterface.FunctionTable.{$IFDEF SSPI_UNICODE}AcquireCredentialsHandleW{$ELSE}AcquireCredentialsHandleA{$ENDIF}(
- pszPrincipal, {$IFDEF SSPI_UNICODE}PSEC_WCHAR{$ELSE}PSEC_CHAR{$ENDIF}(Package.Name), cu, pvLogonId, pAuthData, nil, nil,
- @fHandle, @fExpiry),
- {$IFDEF SSPI_UNICODE}
- 'AcquireCredentialsHandleW' {Do not translater}
- {$ELSE}
- 'AcquireCredentialsHandleA' {Do not translater}
- {$ENDIF}
- );
- fAcquired := True;
- end;
- procedure TSSPICredentials.DoRelease;
- begin
- gSSPIInterface.RaiseIfError(
- gSSPIInterface.FunctionTable.FreeCredentialsHandle(@fHandle),
- 'FreeCredentialsHandle'); {Do not translate}
- SecInvalidateHandle(fHandle);
- end;
- procedure TSSPICredentials.Release;
- begin
- if fAcquired then begin
- DoRelease;
- fAcquired := False;
- end;
- end;
- function TSSPICredentials.GetHandle: PCredHandle;
- begin
- CheckAcquired;
- Result := @fHandle;
- end;
- procedure TSSPICredentials.SetUse(aValue: TSSPICredentialsUse);
- begin
- if fUse <> aValue then begin
- CheckNotAcquired;
- fUse := aValue;
- end;
- end;
- destructor TSSPICredentials.Destroy;
- begin
- Release;
- inherited Destroy;
- end;
- { TSSPIWinNTCredentials }
- procedure TSSPIWinNTCredentials.Acquire(aUse: TSSPICredentialsUse);
- begin
- Acquire(aUse, '', '', ''); {Do not translate}
- end;
- procedure TSSPIWinNTCredentials.Acquire(aUse: TSSPICredentialsUse;
- const aDomain, aUserName, aPassword: {$IFDEF SSPI_UNICODE}TIdUnicodeString{$ELSE}AnsiString{$ENDIF});
- var
- ai: SEC_WINNT_AUTH_IDENTITY;
- pai: PVOID;
- begin
- Use := aUse;
- if (Length(aDomain) > 0) and (Length(aUserName) > 0) then begin
- {$IFDEF SSPI_UNICODE}
- ai.User := PUSHORT(PWideChar(aUserName));
- ai.UserLength := Length(aUserName);
- ai.Domain := PUSHORT(PWideChar(aDomain));
- ai.DomainLength := Length(aDomain);
- ai.Password := PUSHORT(PWideChar(aPassword));
- ai.PasswordLength := Length(aPassword);
- ai.Flags := SEC_WINNT_AUTH_IDENTITY_UNICODE;
- {$ELSE}
- ai.User := PUCHAR(PAnsiChar(aUserName));
- ai.UserLength := Length(aUserName);
- ai.Domain := PUCHAR(PAnsiChar(aDomain));
- ai.DomainLength := Length(aDomain);
- ai.Password := PUCHAR(PAnsiChar(aPassword));
- ai.PasswordLength := Length(aPassword);
- ai.Flags := SEC_WINNT_AUTH_IDENTITY_ANSI;
- {$ENDIF}
- pai := @ai;
- end else
- begin
- pai := nil;
- end;
- DoAcquire(nil, nil, pai);
- end;
- { TSSPIContext }
- constructor TSSPIContext.Create(aCredentials: TSSPICredentials);
- begin
- inherited Create;
- fCredentials := aCredentials;
- fHasHandle := False;
- end;
- destructor TSSPIContext.Destroy;
- begin
- Release;
- inherited Destroy;
- end;
- procedure TSSPIContext.UpdateHasContextAndCheckForError(
- const aFuncResult: SECURITY_STATUS; const aFuncName: string;
- const aErrorsToIgnore: array of SECURITY_STATUS);
- var
- doRaise: Boolean;
- i: Integer;
- begin
- doRaise := not SEC_SUCCESS(aFuncResult);
- if doRaise then begin
- for i := Low(aErrorsToIgnore) to High(aErrorsToIgnore) do begin
- if aFuncResult = aErrorsToIgnore[i] then begin
- doRaise := False;
- Break;
- end;
- end;
- end;
- if doRaise then begin
- raise ESSPIException.CreateError(aFuncResult, aFuncName);
- end;
- fHasHandle := True;
- end;
- function TSSPIContext.DoInitialize(const aTokenSourceName: {$IFDEF SSPI_UNICODE}TIdUnicodeString{$ELSE}AnsiString{$ENDIF};
- var aIn, aOut: SecBufferDesc;
- const errorsToIgnore: array of SECURITY_STATUS): SECURITY_STATUS;
- var
- tmp: PCtxtHandle;
- tmp2: PSecBufferDesc;
- r: ULONG;
- begin
- if fHasHandle then begin
- tmp := @fHandle;
- tmp2 := @aIn;
- end else begin
- tmp := nil;
- tmp2 := nil;
- end;
- Result :=
- gSSPIInterface.FunctionTable.{$IFDEF SSPI_UNICODE}InitializeSecurityContextW{$ELSE}InitializeSecurityContextA{$ENDIF}(
- Credentials.Handle, tmp,
- {$IFDEF SSPI_UNICODE}PWideChar{$ELSE}PAnsiChar{$ENDIF}(aTokenSourceName),
- GetRequestedFlags, 0, SECURITY_NATIVE_DREP, tmp2, 0,
- @fHandle, @aOut, @r, @fExpiry
- );
- UpdateHasContextAndCheckForError(Result,
- {$IFDEF SSPI_UNICODE}'InitializeSecurityContextW'{$ELSE}'InitializeSecurityContextA'{$ENDIF}, {Do not translate}
- errorsToIgnore);
- SetEstablishedFlags(r);
- end;
- procedure TSSPIContext.DoRelease;
- begin
- gSSPIInterface.RaiseIfError(
- gSSPIInterface.FunctionTable.DeleteSecurityContext(@fHandle), 'DeleteSecurityContext'); {Do not translate}
- end;
- procedure TSSPIContext.Release;
- begin
- if HasHandle then begin
- DoRelease;
- fHasHandle := False;
- end;
- end;
- procedure TSSPIContext.CheckHasHandle;
- begin
- if not HasHandle then begin
- raise ESSPIException.Create(RSHTTPSSPINoCredentialHandle);
- end;
- end;
- procedure TSSPIContext.CheckCredentials;
- begin
- if (not Assigned(Credentials)) or (not Credentials.Acquired) then begin
- raise ESSPIException.Create(RSHTTPSSPIDoAuquireCredentialHandle);
- end;
- end;
- function TSSPIContext.GetExpiry: TimeStamp;
- begin
- CheckHasHandle;
- Result := fExpiry;
- end;
- function TSSPIContext.GetHandle: PCtxtHandle;
- begin
- CheckHasHandle;
- Result := @fHandle;
- end;
- { TCustomSSPIConnectionContext }
- procedure TCustomSSPIConnectionContext.DoRelease;
- begin
- inherited DoRelease;
- fStatus := SEC_E_INVALID_HANDLE; // just to put something other then SEC_E_OK
- end;
- function TCustomSSPIConnectionContext.GetAuthenticated: Boolean;
- begin
- CheckHasHandle;
- Result := fStatus = SEC_E_OK;
- end;
- function TCustomSSPIConnectionContext.UpdateAndGenerateReply
- (const aFromPeerToken: TIdBytes; var aToPeerToken: TIdBytes): Boolean;
- var
- fOutBuff: SecBuffer;
- begin
- // keep the compiler happy (when was this fixed exactly?)
- {$IFDEF DCC}{$IFNDEF VCL_8_OR_ABOVE}
- Result := False;
- {$ENDIF}{$ENDIF}
- { check credentials }
- CheckCredentials;
- { prepare input buffer }
- fInBuff.cbBuffer := Length(aFromPeerToken);
- //Assert(Length(aFromPeerToken)>0);
- if fInBuff.cbBuffer > 0 then begin
- fInBuff.pvBuffer := @aFromPeerToken[0];
- end;
- { prepare output buffer }
- fOutBuff.BufferType := SECBUFFER_TOKEN;
- fOutBuff.cbBuffer := Credentials.Package.MaxToken;
- fOutBuff.pvBuffer := AllocMem(fOutBuff.cbBuffer);
- fOutBuffDesc.ulVersion := SECBUFFER_VERSION;
- fOutBuffDesc.cBuffers := 1;
- fOutBuffDesc.pBuffers := @fOutBuff;
- try
- { do processing }
- fStatus := DoUpdateAndGenerateReply(fInBuffDesc, fOutBuffDesc, []);
- { complete token if applicable }
- case fStatus of
- SEC_I_COMPLETE_NEEDED,
- SEC_I_COMPLETE_AND_CONTINUE:
- begin
- if not Assigned(gSSPIInterface.FunctionTable.CompleteAuthToken) then begin
- raise ESSPIException.Create(RSHTTPSSPICompleteTokenNotSupported);
- end;
- fStatus := gSSPIInterface.FunctionTable.CompleteAuthToken(Handle, @fOutBuffDesc);
- gSSPIInterface.RaiseIfError(fStatus, 'CompleteAuthToken'); {Do not translate}
- end;
- end;
- Result :=
- (fStatus = SEC_I_CONTINUE_NEEDED) or
- (fStatus = SEC_I_COMPLETE_AND_CONTINUE) or
- (fOutBuff.cbBuffer > 0);
- if Result then begin
- aToPeerToken := RawToBytes(fOutBuff.pvBuffer^, fOutBuff.cbBuffer);
- end;
- finally
- FreeMem(fOutBuff.pvBuffer);
- end;
- end;
- constructor TCustomSSPIConnectionContext.Create(aCredentials: TSSPICredentials);
- begin
- inherited Create(aCredentials);
- fInBuff.BufferType := SECBUFFER_TOKEN;
- fInBuffDesc.ulVersion := SECBUFFER_VERSION;
- fInBuffDesc.cBuffers := 1;
- fInBuffDesc.pBuffers := @fInBuff;
- fOutBuffDesc.ulVersion := SECBUFFER_VERSION;
- fOutBuffDesc.cBuffers := 1;
- end;
- { TSSPIClientConnectionContext }
- constructor TSSPIClientConnectionContext.Create(aCredentials: TSSPICredentials);
- begin
- inherited Create(aCredentials);
- fTargetName := ''; {Do not translate}
- end;
- function TSSPIClientConnectionContext.GetRequestedFlags: ULONG;
- begin
- Result := fReqReguested;
- end;
- procedure TSSPIClientConnectionContext.SetEstablishedFlags(aFlags: ULONG);
- begin
- fReqEstablished := aFlags;
- end;
- function TSSPIClientConnectionContext.DoUpdateAndGenerateReply
- (var aIn, aOut: SecBufferDesc;
- const aErrorsToIgnore: array of SECURITY_STATUS): SECURITY_STATUS;
- begin
- Result := DoInitialize(fTargetName, aIn, aOut, []);
- end;
- function TSSPIClientConnectionContext.GenerateInitialChallenge
- (const aTargetName: string; var aToPeerToken: TIdBytes): Boolean;
- begin
- Release;
- fTargetName := aTargetName;
- Result := UpdateAndGenerateReply(nil, aToPeerToken); {Do not translate}
- end;
- { TIndySSPINTLMClient }
- constructor TIndySSPINTLMClient.Create;
- begin
- inherited Create;
- fNTLMPackage := TSSPINTLMPackage.Create;
- fCredentials := TSSPIWinNTCredentials.Create(fNTLMPackage);
- fContext := TSSPIClientConnectionContext.Create(fCredentials);
- end;
- destructor TIndySSPINTLMClient.Destroy;
- begin
- FreeAndNil(fContext);
- FreeAndNil(fCredentials);
- FreeAndNil(fNTLMPackage);
- inherited Destroy;
- end;
- procedure TIndySSPINTLMClient.SetCredentials(const aDomain, aUserName, aPassword: string);
- begin
- fCredentials.Acquire(scuOutBound, aDomain, aUserName, aPassword);
- end;
- procedure TIndySSPINTLMClient.SetCredentialsAsCurrentUser;
- begin
- fCredentials.Acquire(scuOutBound);
- end;
- function TIndySSPINTLMClient.InitAndBuildType1Message: TIdBytes;
- begin
- fContext.GenerateInitialChallenge('', Result);
- end;
- function TIndySSPINTLMClient.UpdateAndBuildType3Message(const aServerType2Message: TIdBytes): TIdBytes;
- begin
- fContext.UpdateAndGenerateReply(aServerType2Message, Result);
- end;
- { TIdSSPINTLMAuthentication }
- constructor TIdSSPINTLMAuthentication.Create;
- begin
- inherited Create;
- FSSPIClient := TIndySSPINTLMClient.Create;
- Domain := IndyComputerName;
- end;
- function TIdSSPINTLMAuthentication.DoNext: TIdAuthWhatsNext;
- begin
- Result := wnDoRequest;
- case FCurrentStep of
- //Authentication() does the 2>3 progression
- 0, 1, 3:
- begin
- Inc(FCurrentStep);
- Result := wnDoRequest;
- end;
- 4:
- begin
- FCurrentStep := 0;
- if Username = '' then begin
- Result := wnAskTheProgram;
- end else begin
- Result := wnFail;
- Username := '';
- Password := '';
- Domain := IndyComputerName;
- end;
- end;
- end;
- end;
- function TIdSSPINTLMAuthentication.Authentication: string;
- var
- buf: TIdBytes;
- begin
- Result := '';
- buf := nil;
- case FCurrentStep of
- 1:
- begin
- if Length(Username) = 0 then begin
- FSSPIClient.SetCredentialsAsCurrentUser;
- end else begin
- FSSPIClient.SetCredentials(Domain, Username, Password);
- end;
- Result := 'NTLM ' + TIdEncoderMIME.EncodeBytes(FSSPIClient.InitAndBuildType1Message); {Do not translate}
- FNTLMInfo := ''; {Do not translate}
- end;
- 2:
- begin
- if Length(FNTLMInfo) = 0 then begin
- FNTLMInfo := ReadAuthInfo('NTLM'); {Do not translate}
- Fetch(FNTLMInfo);
- end;
- if Length(FNTLMInfo) = 0 then begin
- Reset;
- Abort;
- end;
- buf := TIdDecoderMIME.DecodeBytes(FNTLMInfo);
- Result := 'NTLM ' + TIdEncoderMIME.EncodeBytes(FSSPIClient.UpdateAndBuildType3Message(buf)); {Do not translate}
- FCurrentStep := 3;
- end;
- 3: begin
- FCurrentStep := 4;
- end;
- end;
- end;
- function TIdSSPINTLMAuthentication.KeepAlive: Boolean;
- begin
- Result := FCurrentStep >= 1;
- end;
- function TIdSSPINTLMAuthentication.GetSteps: Integer;
- begin
- Result := 3;
- end;
- procedure TIdSSPINTLMAuthentication.SetDomain(const Value: String);
- begin
- Params.Values['Domain'] := Value; {do not localize}
- end;
- function TIdSSPINTLMAuthentication.GetDomain: String;
- begin
- Result := Params.Values['Domain']; {do not localize}
- end;
- procedure TIdSSPINTLMAuthentication.SetUserName(const Value: String);
- var
- S: String;
- Idx: Integer;
- begin
- S := Value;
- Idx := IndyPos('\', S);
- if Idx > 0 then begin
- Domain := Copy(S, 1, Idx - 1);
- Delete(S, 1, Idx);
- end;
- inherited SetUserName(S);
- end;
- destructor TIdSSPINTLMAuthentication.Destroy;
- begin
- FreeAndNil(FSSPIClient);
- inherited;
- end;
- initialization
- gSSPIInterface := TSSPIInterface.Create;
- if gSSPIInterface.IsAvailable then begin
- RegisterAuthenticationMethod('NTLM', TIdSSPINTLMAuthentication); {do not localize}
- RegisterAuthenticationMethod('Negotiate', TIdSSPINTLMAuthentication); {do not localize}
- gAuthRegistered := True;
- end;
- finalization
- if gAuthRegistered then begin
- UnregisterAuthenticationMethod('NTLM'); {do not localize}
- UnregisterAuthenticationMethod('Negotiate'); {do not localize}
- end;
- FreeAndNil(gSSPIInterface);
- end.
|