1 module server; 2 version(Windows): 3 import sspi; 4 import std.socket : Socket; 5 import core.sys.windows.ntsecpkg : SECURITY_NATIVE_DREP; 6 7 enum BackLog = 10; 8 9 // Port of Microsoft example for server-side SSPI Windows Sockets program. 10 11 int main(string[] args) 12 { 13 import std.conv : to; 14 import std.stdio : writefln; 15 16 ushort serverPort = (args.length > 1) ? args[1].to!ushort : 9000.to!ushort; 17 auto serverAuth = ServerAuth(); // "Negotiate", ServerAuth.DefaultSecurityContextFlags, SECURITY_NATIVE_DREP); 18 serverAuth.setup(); 19 auto maxMessageSize = serverAuth.packageInfo.cbMaxToken; 20 ubyte[] inBuf = new ubyte[maxMessageSize]; 21 ubyte[] outBuf = new ubyte[maxMessageSize]; 22 23 24 //----------------------------------------------------------------- 25 // Start looping for clients. 26 27 while(true) 28 { 29 writefln("Waiting for client to connect..."); 30 31 // Make an authenticated connection with client. 32 auto socket = serverAuth.acceptAuthSocket(serverPort); 33 auto securityPackageContextSizes = queryContextAttributes!SecPkgContext_Sizes(&serverAuth.context,SecPackageAttribute.sizes); 34 //---------------------------------------------------------------- 35 // The following values are used for encryption and signing. 36 37 auto cbMaxSignature = securityPackageContextSizes.cbMaxSignature; 38 auto cbSecurityTrailer = securityPackageContextSizes.cbSecurityTrailer; 39 40 auto securityPackageNegInfo = queryContextAttributes!SecPkgContext_NegotiationInfoW(&serverAuth.context,SecPackageAttribute.negotiationInfo); 41 writefln("Package Name: %s", securityPackageNegInfo.packageInfo.Name); 42 43 // impersonate the client 44 auto userName = serverAuth.impersonate(); 45 writefln("Impersonation worked."); 46 writefln("Client connected as: %s",userName); 47 48 // Revert to self. 49 serverAuth.revertImpersonate(); 50 writefln("Reverted to self."); 51 52 // Send the client an encrypted message. 53 auto message = "This is your server speaking"; 54 auto encryptedMessage = serverAuth.encrypt(message); 55 56 //----------------------------------------------------------------- 57 // Send the encrypted data to client. 58 59 socket.sendBytes(encryptedMessage); 60 writefln(" %s encrypted bytes sent.", encryptedMessage.length); 61 serverAuth.dispose(); 62 serverAuth = ServerAuth("Negotiate", ServerAuth.DefaultSecurityContextFlags, SECURITY_NATIVE_DREP); 63 serverAuth.setup(); 64 } 65 66 //writefln("Server ran to completion without error."); 67 } 68 69 Socket acceptAuthSocket(ref ServerAuth server, ushort serverPort) 70 { 71 import std.socket : getAddressInfo, AddressFamily, Socket, InternetAddress; 72 import std.algorithm : filter; 73 import std.array : array; 74 import std.range : front; 75 import std.exception : enforce; 76 import std.conv : to; 77 78 // Lookup the server's address. 79 auto addressInfos = getAddressInfo("0.0.0.0") 80 .filter!(info => info.family == AddressFamily.INET) 81 .array; 82 83 auto address = new InternetAddress("0.0.0.0", serverPort); 84 85 // Create the socket. 86 Socket socket = new Socket(addressInfos.front); 87 socket.bind(address); 88 89 // Listen 90 socket.listen(BackLog); 91 auto client = socket.accept(); 92 socket.close(); 93 94 auto messageResult = server.authorize(); 95 enforce(messageResult[0] == SecurityStatus.okay); 96 auto message = messageResult[1]; 97 client.sendMessage(message); 98 message = socket.receiveMessage().idup; 99 auto result = server.authorize(message); 100 enforce(result[0] == SecurityStatus.okay, result[0].to!string); 101 client.sendMessage(result[1]); 102 return client; 103 } 104 105 106 void printHexDump(const(ubyte)[] buf) 107 { 108 import std.stdio : writefln; 109 import std.format : format; 110 111 size_t i,count,index; 112 char[] rgbDigits="0123456789abcdef".dup; 113 char[100] rgbLine; 114 char cbLine; 115 auto length = buf.length; 116 char* buffer = cast(char*)buf.ptr; 117 118 for(index = 0; length; length -= count, buffer += count, index += count) 119 { 120 count = (length > 16) ? 16:length; 121 122 rgbLine = format!"%s4.4x "(index); 123 cbLine = 6; 124 125 for(i=0;i<count;i++) 126 { 127 rgbLine[cbLine++] = rgbDigits[buffer[i] >> 4]; 128 rgbLine[cbLine++] = rgbDigits[buffer[i] & 0x0f]; 129 if(i == 7) 130 { 131 rgbLine[cbLine++] = ':'; 132 } 133 else 134 { 135 rgbLine[cbLine++] = ' '; 136 } 137 } 138 for(; i < 16; i++) 139 { 140 rgbLine[cbLine++] = ' '; 141 rgbLine[cbLine++] = ' '; 142 rgbLine[cbLine++] = ' '; 143 } 144 145 rgbLine[cbLine++] = ' '; 146 147 for(i = 0; i < count; i++) 148 { 149 if(buffer[i] < 32 || buffer[i] > 126) 150 { 151 rgbLine[cbLine++] = '.'; 152 } 153 else 154 { 155 rgbLine[cbLine++] = buffer[i]; 156 } 157 } 158 159 rgbLine[cbLine++] = 0; 160 writefln("%s", rgbLine); 161 } 162 } 163 164 void sendMessage(Socket socket, const(ubyte)[] message) 165 { 166 import std.conv : to; 167 auto messageLength = message.length.to!ulong; 168 socket.sendBytes((cast(ubyte*)&messageLength)[0..4]); 169 socket.sendBytes(message); 170 } 171 172 ubyte[] receiveMessage(Socket socket) 173 { 174 import std.exception : enforce; 175 import std.conv : to; 176 177 ubyte[4] messageLengthBuf; 178 enforce(socket.receive(messageLengthBuf) ==4); 179 auto messageLength = (*(cast(ulong*)(messageLengthBuf.ptr))).to!size_t; 180 auto message = socket.receiveBytes(messageLength); 181 return message; 182 } 183 184 void sendBytes(Socket socket, const(ubyte)[] buf) 185 { 186 size_t numBytesRemaining = buf.length; 187 size_t numBytesSent = 0; 188 189 if (buf.length == 0) 190 return; 191 192 while(numBytesRemaining > 0) 193 { 194 auto cbSent = socket.send(buf[numBytesSent .. $]); 195 numBytesSent += cbSent; 196 numBytesRemaining -= cbSent; 197 } 198 } 199 200 ubyte[] receiveBytes(Socket socket, size_t messageLength = 0) 201 { 202 import std.array : Appender; 203 import std.conv : to; 204 205 Appender!(ubyte[]) ret; 206 ubyte[1024] buf; 207 long cbRead, cbRemaining = messageLength; 208 209 while (cbRemaining) 210 { 211 cbRead = socket.receive(buf); 212 ret.put(buf[0 .. cbRead.to!size_t]); 213 cbRemaining -= cbRead; 214 } 215 return ret.data; 216 } 217 218