1 module sspi.helpers; 2 3 /+ 4 Helper classes for SSPI authentication via the win32security module. 5 SSPI authentication involves a token-exchange "dance", the exact details 6 of which depends on the authentication provider used. There are also 7 a number of complex flags and constants that need to be used - in most 8 cases, there are reasonable defaults. 9 These classes attempt to hide these details from you until you really need 10 to know. They are not designed to handle all cases, just the common ones. 11 If you need finer control than offered here, just use the win32security 12 functions directly. 13 +/ 14 15 /// Based on Roger Upole's sspi demos. 16 version(Windows): 17 import core.sys.windows.ntsecpkg; 18 import core.sys.windows.sspi; 19 import core.sys.windows.security; 20 import std.exception; 21 import sspi.defines; 22 import std.typecons:tuple; 23 import std.conv:to; 24 import std.utf:toUTF16z; 25 26 bool secSuccess(SECURITY_STATUS status) 27 { 28 return status >= 0; 29 } 30 31 T queryContextAttributes(T)(SecHandle* context, SecPackageAttribute attribute) 32 { 33 T ret; 34 auto securityStatus = QueryContextAttributesW(context,attribute,cast(void*)&ret); 35 enforce(securityStatus.secSuccess, (cast(SecurityStatus)securityStatus).to!string); 36 return ret; 37 } 38 39 uint decryptMessage(ref SecHandle context, ref SecBufferDesc message, uint messageSeqNo) 40 { 41 uint fQOP; 42 auto securityStatus = DecryptMessage(&context,&message,messageSeqNo,&fQOP); 43 enforce(securityStatus.secSuccess, (cast(SecurityStatus)securityStatus).to!string); 44 return fQOP; 45 } 46 47 void encryptMessage(ref SecHandle context, uint fQOP, ref SecBufferDesc message, uint messageSeqNo) 48 { 49 auto securityStatus = EncryptMessage(&context,fQOP, &message,messageSeqNo); 50 enforce(securityStatus.secSuccess, (cast(SecurityStatus)securityStatus).to!string); 51 } 52 53 void makeSignature(ref SecHandle context, uint fQOP, ref SecBufferDesc message, uint messageSeqNo) 54 { 55 auto securityStatus = MakeSignature(&context,fQOP,&message,messageSeqNo); 56 enforce(securityStatus.secSuccess, (cast(SecurityStatus)securityStatus).to!string); 57 } 58 59 uint verifySignature(ref SecHandle context, ref SecBufferDesc message, uint messageSeqNo) 60 { 61 uint pfQOP; 62 auto securityStatus = VerifySignature(&context,&message,messageSeqNo,&pfQOP); 63 enforce(securityStatus.secSuccess, (cast(SecurityStatus)securityStatus).to!string); 64 return pfQOP; 65 } 66 67 68 auto querySecurityPackageInfo(string packageName) 69 { 70 PSecPkgInfoW ret; 71 SecurityStatus securityStatus = cast(SecurityStatus) QuerySecurityPackageInfoW(cast(wchar*)packageName.toUTF16z,&ret); 72 enforce(securityStatus.secSuccess, securityStatus.to!string); 73 return ret; 74 } 75 76 struct SecurityContextResult 77 { 78 uint contextAttribute; 79 TimeStamp expiry; 80 SecurityStatus securityStatus; 81 SecBufferDesc outputBufferDesc; 82 } 83 84 auto initializeSecurityContext(ref CredHandle credentials, SecHandle* context, string targetName, uint fContextReq, ulong reserved1, uint targetDataRep, SecBufferDesc* input, ref SecBufferDesc outputBufferDesc) 85 { 86 SecurityContextResult ret; 87 ret.outputBufferDesc = outputBufferDesc; 88 ret.securityStatus = cast(SecurityStatus) InitializeSecurityContextW(&credentials, context, cast(wchar*)targetName.toUTF16z, fContextReq, 0, targetDataRep,input,0,context,&ret.outputBufferDesc,&ret.contextAttribute,&ret.expiry); 89 return ret; 90 } 91 92 auto initializeSecurityContext(ref CredHandle credentials, SecHandle* context, string targetName, uint fContextReq, ulong reserved1, uint targetDataRep, ref SecBufferDesc input, ref SecBufferDesc outputBufferDesc) 93 { 94 return initializeSecurityContext(credentials, context, targetName, fContextReq, reserved1, targetDataRep,&input,outputBufferDesc); 95 } 96 97 auto initializeSecurityContextInitial(ref CredHandle credentials, SecHandle* context, string targetName, uint fContextReq, ulong reserved1, uint targetDataRep, ref SecBufferDesc outputBufferDesc) 98 { 99 SecurityContextResult ret; 100 ret.outputBufferDesc = outputBufferDesc; 101 version(Trace) 102 { 103 import std.stdio; 104 writefln("targetName: %s",targetName); 105 writefln("fcontextReq: %s",fContextReq); 106 writeln("targetDataRep: %s",targetDataRep); 107 } 108 ret.securityStatus = cast(SecurityStatus) InitializeSecurityContextW(&credentials,null,(targetName.length==0)? null : cast(wchar*)targetName.toUTF16z, fContextReq, 0, targetDataRep,null,0,context,&ret.outputBufferDesc,&ret.contextAttribute,&ret.expiry); 109 return ret; 110 } 111 112 void completeAuthToken(SecHandle* context, ref SecBufferDesc token) 113 { 114 auto securityStatus = CompleteAuthToken(context,&token); 115 enforce(securityStatus.secSuccess, (cast(SecurityStatus)securityStatus).to!string); 116 } 117