|
| 1 | +Param([parameter(Mandatory=$true, |
| 2 | + HelpMessage="Enter server url [ -server <server url> ]")] |
| 3 | + $serverUrl |
| 4 | + ) |
| 5 | +if(!$serverUrl){ |
| 6 | +return "Enter server url [ -server <server url> ]" |
| 7 | +} |
| 8 | +function GetBigFixToken { |
| 9 | + [CmdletBinding()] |
| 10 | + param($PN) |
| 11 | + $Signature = @" |
| 12 | +
|
| 13 | +public enum SecBufferType |
| 14 | +{ |
| 15 | + SECBUFFER_VERSION = 0, |
| 16 | + SECBUFFER_EMPTY = 0, |
| 17 | + SECBUFFER_DATA = 1, |
| 18 | + SECBUFFER_TOKEN = 2 |
| 19 | +} |
| 20 | +
|
| 21 | +[StructLayout(LayoutKind.Sequential)] |
| 22 | +public struct SECURITY_INTEGER |
| 23 | +{ |
| 24 | + public uint LowPart; |
| 25 | + public int HighPart; |
| 26 | + public SECURITY_INTEGER(int dummy) |
| 27 | + { |
| 28 | + LowPart = 0; |
| 29 | + HighPart = 0; |
| 30 | + } |
| 31 | +}; |
| 32 | +
|
| 33 | +[StructLayout(LayoutKind.Sequential)] |
| 34 | +public struct SecBuffer : IDisposable |
| 35 | +{ |
| 36 | + public int cbBuffer; |
| 37 | + public int BufferType; |
| 38 | + public IntPtr pvBuffer; |
| 39 | +
|
| 40 | +
|
| 41 | + public SecBuffer(int bufferSize) |
| 42 | + { |
| 43 | + cbBuffer = bufferSize; |
| 44 | + BufferType = (int)SecBufferType.SECBUFFER_TOKEN; |
| 45 | + pvBuffer = Marshal.AllocHGlobal(bufferSize); |
| 46 | + } |
| 47 | +
|
| 48 | + public SecBuffer(byte[] secBufferBytes) |
| 49 | + { |
| 50 | + cbBuffer = secBufferBytes.Length; |
| 51 | + BufferType = (int)SecBufferType.SECBUFFER_TOKEN; |
| 52 | + pvBuffer = Marshal.AllocHGlobal(cbBuffer); |
| 53 | + Marshal.Copy(secBufferBytes,0,pvBuffer,cbBuffer); |
| 54 | + } |
| 55 | +
|
| 56 | + public SecBuffer(byte[] secBufferBytes,SecBufferType bufferType) |
| 57 | + { |
| 58 | + cbBuffer = secBufferBytes.Length; |
| 59 | + BufferType = (int)bufferType; |
| 60 | + pvBuffer = Marshal.AllocHGlobal(cbBuffer); |
| 61 | + Marshal.Copy(secBufferBytes,0,pvBuffer,cbBuffer); |
| 62 | + } |
| 63 | +
|
| 64 | + public void Dispose() |
| 65 | + { |
| 66 | + if(pvBuffer != IntPtr.Zero) |
| 67 | + { |
| 68 | + Marshal.FreeHGlobal(pvBuffer); |
| 69 | + pvBuffer = IntPtr.Zero; |
| 70 | + } |
| 71 | + } |
| 72 | +} |
| 73 | +
|
| 74 | +public struct MultipleSecBufferHelper |
| 75 | +{ |
| 76 | + public byte[] Buffer; |
| 77 | + public SecBufferType BufferType; |
| 78 | +
|
| 79 | + public MultipleSecBufferHelper(byte[] buffer,SecBufferType bufferType) |
| 80 | + { |
| 81 | + if(buffer == null || buffer.Length == 0) |
| 82 | + { |
| 83 | + throw new ArgumentException("buffer cannot be null or 0 length"); |
| 84 | + } |
| 85 | +
|
| 86 | + Buffer = buffer; |
| 87 | + BufferType = bufferType; |
| 88 | + } |
| 89 | +}; |
| 90 | +
|
| 91 | +[StructLayout(LayoutKind.Sequential)] |
| 92 | +public struct SecBufferDesc : IDisposable |
| 93 | +{ |
| 94 | +
|
| 95 | + public int ulVersion; |
| 96 | + public int cBuffers; |
| 97 | + public IntPtr pBuffers; //Point to SecBuffer |
| 98 | +
|
| 99 | + public SecBufferDesc(int bufferSize) |
| 100 | + { |
| 101 | + ulVersion = (int)SecBufferType.SECBUFFER_VERSION; |
| 102 | + cBuffers = 1; |
| 103 | + SecBuffer ThisSecBuffer = new SecBuffer(bufferSize); |
| 104 | + pBuffers = Marshal.AllocHGlobal(Marshal.SizeOf(ThisSecBuffer)); |
| 105 | + Marshal.StructureToPtr(ThisSecBuffer,pBuffers,false); |
| 106 | + } |
| 107 | +
|
| 108 | + public SecBufferDesc(byte[] secBufferBytes) |
| 109 | + { |
| 110 | + ulVersion = (int)SecBufferType.SECBUFFER_VERSION; |
| 111 | + cBuffers = 1; |
| 112 | + SecBuffer ThisSecBuffer = new SecBuffer(secBufferBytes); |
| 113 | + pBuffers = Marshal.AllocHGlobal(Marshal.SizeOf(ThisSecBuffer)); |
| 114 | + Marshal.StructureToPtr(ThisSecBuffer,pBuffers,false); |
| 115 | + } |
| 116 | +
|
| 117 | + public SecBufferDesc(MultipleSecBufferHelper[] secBufferBytesArray) |
| 118 | + { |
| 119 | + if(secBufferBytesArray == null || secBufferBytesArray.Length == 0) |
| 120 | + { |
| 121 | + throw new ArgumentException("secBufferBytesArray cannot be null or 0 length"); |
| 122 | + } |
| 123 | +
|
| 124 | + ulVersion = (int)SecBufferType.SECBUFFER_VERSION; |
| 125 | + cBuffers = secBufferBytesArray.Length; |
| 126 | +
|
| 127 | + pBuffers = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(SecBuffer)) * cBuffers); |
| 128 | +
|
| 129 | + for(int Index = 0;Index < secBufferBytesArray.Length;Index++) |
| 130 | + { |
| 131 | + SecBuffer ThisSecBuffer = new SecBuffer(secBufferBytesArray[Index].Buffer,secBufferBytesArray[Index].BufferType); |
| 132 | +
|
| 133 | + int CurrentOffset = Index*Marshal.SizeOf(typeof(SecBuffer)); |
| 134 | + Marshal.WriteInt32(pBuffers,CurrentOffset,ThisSecBuffer.cbBuffer); |
| 135 | + Marshal.WriteInt32(pBuffers,CurrentOffset + Marshal.SizeOf(ThisSecBuffer.cbBuffer),ThisSecBuffer.BufferType); |
| 136 | + Marshal.WriteIntPtr(pBuffers,CurrentOffset + Marshal.SizeOf(ThisSecBuffer.cbBuffer)+Marshal.SizeOf(ThisSecBuffer.BufferType),ThisSecBuffer.pvBuffer); |
| 137 | + } |
| 138 | + } |
| 139 | +
|
| 140 | + public void Dispose() |
| 141 | + { |
| 142 | + if(pBuffers != IntPtr.Zero) |
| 143 | + { |
| 144 | + if(cBuffers == 1) |
| 145 | + { |
| 146 | + SecBuffer ThisSecBuffer = (SecBuffer)Marshal.PtrToStructure(pBuffers,typeof(SecBuffer)); |
| 147 | + ThisSecBuffer.Dispose(); |
| 148 | + } |
| 149 | + else |
| 150 | + { |
| 151 | + for(int Index = 0;Index < cBuffers;Index++) |
| 152 | + { |
| 153 | + int CurrentOffset = Index*Marshal.SizeOf(typeof(SecBuffer)); |
| 154 | + IntPtr SecBufferpvBuffer = Marshal.ReadIntPtr(pBuffers,CurrentOffset + Marshal.SizeOf(typeof(int))+Marshal.SizeOf(typeof(int))); |
| 155 | + Marshal.FreeHGlobal(SecBufferpvBuffer); |
| 156 | + } |
| 157 | + } |
| 158 | +
|
| 159 | + Marshal.FreeHGlobal(pBuffers); |
| 160 | + pBuffers = IntPtr.Zero; |
| 161 | + } |
| 162 | + } |
| 163 | +
|
| 164 | + public byte[] GetSecBufferByteArray() |
| 165 | + { |
| 166 | + byte[] Buffer = null; |
| 167 | +
|
| 168 | + if(pBuffers == IntPtr.Zero) |
| 169 | + { |
| 170 | + throw new InvalidOperationException("Object has already been disposed!!!"); |
| 171 | + } |
| 172 | +
|
| 173 | + if(cBuffers == 1) |
| 174 | + { |
| 175 | + SecBuffer ThisSecBuffer = (SecBuffer)Marshal.PtrToStructure(pBuffers,typeof(SecBuffer)); |
| 176 | +
|
| 177 | + if(ThisSecBuffer.cbBuffer > 0) |
| 178 | + { |
| 179 | + Buffer = new byte[ThisSecBuffer.cbBuffer]; |
| 180 | + Marshal.Copy(ThisSecBuffer.pvBuffer,Buffer,0,ThisSecBuffer.cbBuffer); |
| 181 | + } |
| 182 | + } |
| 183 | + else |
| 184 | + { |
| 185 | + int BytesToAllocate = 0; |
| 186 | +
|
| 187 | + for(int Index = 0;Index < cBuffers;Index++) |
| 188 | + { |
| 189 | + int CurrentOffset = Index*Marshal.SizeOf(typeof(SecBuffer)); |
| 190 | + BytesToAllocate += Marshal.ReadInt32(pBuffers,CurrentOffset); |
| 191 | + } |
| 192 | +
|
| 193 | + Buffer = new byte[BytesToAllocate]; |
| 194 | +
|
| 195 | + for(int Index = 0,BufferIndex = 0;Index < cBuffers;Index++) |
| 196 | + { |
| 197 | + int CurrentOffset = Index*Marshal.SizeOf(typeof(SecBuffer)); |
| 198 | + int BytesToCopy = Marshal.ReadInt32(pBuffers,CurrentOffset); |
| 199 | + IntPtr SecBufferpvBuffer = Marshal.ReadIntPtr(pBuffers,CurrentOffset + Marshal.SizeOf(typeof(int))+Marshal.SizeOf(typeof(int))); |
| 200 | + Marshal.Copy(SecBufferpvBuffer,Buffer,BufferIndex,BytesToCopy); |
| 201 | + BufferIndex += BytesToCopy; |
| 202 | + } |
| 203 | + } |
| 204 | +
|
| 205 | + return(Buffer); |
| 206 | + } |
| 207 | +
|
| 208 | + public SecBuffer GetSecBuffer() |
| 209 | + { |
| 210 | + if(pBuffers == IntPtr.Zero) |
| 211 | + { |
| 212 | + throw new InvalidOperationException("Object has already been disposed!!!"); |
| 213 | + } |
| 214 | +
|
| 215 | + return((SecBuffer)Marshal.PtrToStructure(pBuffers,typeof(SecBuffer))); |
| 216 | + } |
| 217 | +} |
| 218 | +
|
| 219 | +[StructLayout(LayoutKind.Sequential)] |
| 220 | +public struct SECURITY_HANDLE |
| 221 | +{ |
| 222 | + public uint LowPart; |
| 223 | + public uint HighPart; |
| 224 | + public SECURITY_HANDLE(int dummy) |
| 225 | + { |
| 226 | + LowPart = HighPart = 0; |
| 227 | + } |
| 228 | +}; |
| 229 | +
|
| 230 | +
|
| 231 | +[DllImport("secur32.dll", SetLastError=true)] |
| 232 | +static extern int AcquireCredentialsHandle( |
| 233 | + string pszPrincipal, //SEC_CHAR* |
| 234 | + string pszPackage, //SEC_CHAR* //"Kerberos","NTLM","Negotiative" |
| 235 | + int fCredentialUse, |
| 236 | + IntPtr PAuthenticationID,//_LUID AuthenticationID,//pvLogonID, //PLUID |
| 237 | + IntPtr pAuthData,//PVOID |
| 238 | + int pGetKeyFn, //SEC_GET_KEY_FN |
| 239 | + IntPtr pvGetKeyArgument, //PVOID |
| 240 | + ref SECURITY_HANDLE phCredential, //SecHandle //PCtxtHandle ref |
| 241 | + ref SECURITY_INTEGER ptsExpiry //PTimeStamp //TimeStamp ref |
| 242 | +); |
| 243 | +
|
| 244 | +[DllImport("secur32.dll", SetLastError=true)] |
| 245 | +static extern int InitializeSecurityContext( |
| 246 | + ref SECURITY_HANDLE phCredential,//PCredHandle |
| 247 | + IntPtr phContext, //PCtxtHandle |
| 248 | + string pszTargetName, |
| 249 | + int fContextReq, |
| 250 | + int Reserved1, |
| 251 | + int TargetDataRep, |
| 252 | + IntPtr pInput, //PSecBufferDesc SecBufferDesc |
| 253 | + int Reserved2, |
| 254 | + out SECURITY_HANDLE phNewContext, //PCtxtHandle |
| 255 | + out SecBufferDesc pOutput, //PSecBufferDesc SecBufferDesc |
| 256 | + out uint pfContextAttr, //managed ulong == 64 bits!!! |
| 257 | + out SECURITY_INTEGER ptsExpiry //PTimeStamp |
| 258 | +); |
| 259 | +
|
| 260 | +public static SECURITY_HANDLE phCredential; |
| 261 | +public static SECURITY_INTEGER ptsExpiry; |
| 262 | +
|
| 263 | +public const int ISC_REQ_DELEGATE = 0x00000001; |
| 264 | +public const int ISC_REQ_MUTUAL_AUTH = 0x00000002; |
| 265 | +public const int ISC_REQ_CONFIDENTIALITY = 0x00000010; |
| 266 | +public const int ISC_REQ_ALLOCATE_MEMORY = 0x00000100; |
| 267 | +public const int ISC_REQ_CONNECTION = 0x00000800; |
| 268 | +public const int ISC_REQ_INTEGRITY = 0x00010000; |
| 269 | +
|
| 270 | +
|
| 271 | +public const int STANDARD_CONTEXT_ATTRIBUTES = ISC_REQ_CONNECTION | ISC_REQ_MUTUAL_AUTH | ISC_REQ_DELEGATE | ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY | ISC_REQ_ALLOCATE_MEMORY ; |
| 272 | +public const int SECURITY_NETWORK_DREP = 0x00000000; |
| 273 | +
|
| 274 | +public const int SEC_E_OK = 0; |
| 275 | +public const int SECPKG_CRED_BOTH = 3; |
| 276 | +
|
| 277 | +const int MAX_TOKEN_SIZE = 12288; |
| 278 | +
|
| 279 | +public static SecBufferDesc ClientToken = new SecBufferDesc(MAX_TOKEN_SIZE); |
| 280 | +public static uint ContextAttributes = 0; |
| 281 | +public static SECURITY_HANDLE _hClientContext = new SECURITY_HANDLE(0); |
| 282 | +public static SECURITY_INTEGER ptsexp; |
| 283 | +
|
| 284 | +
|
| 285 | +public static int GetPrincipalName() { |
| 286 | + return AcquireCredentialsHandle( |
| 287 | + "", |
| 288 | + "Kerberos", |
| 289 | + SECPKG_CRED_BOTH, |
| 290 | + IntPtr.Zero, |
| 291 | + IntPtr.Zero, |
| 292 | + 0, |
| 293 | + IntPtr.Zero, |
| 294 | + ref phCredential, |
| 295 | + ref ptsExpiry); |
| 296 | +} |
| 297 | +
|
| 298 | +public static string GetToken(string pn) { |
| 299 | + if( GetPrincipalName() != SEC_E_OK ) { |
| 300 | + throw new Exception("Unable to get PrincipleName"); |
| 301 | + } |
| 302 | +
|
| 303 | + InitializeSecurityContext( |
| 304 | + ref phCredential, |
| 305 | + IntPtr.Zero, |
| 306 | + pn, |
| 307 | + STANDARD_CONTEXT_ATTRIBUTES, |
| 308 | + 0, |
| 309 | + SECURITY_NETWORK_DREP, |
| 310 | + IntPtr.Zero, |
| 311 | + 0, |
| 312 | + out _hClientContext, |
| 313 | + out ClientToken, |
| 314 | + out ContextAttributes, |
| 315 | + out ptsexp |
| 316 | + ); |
| 317 | +
|
| 318 | + byte[] token_a = ClientToken.GetSecBufferByteArray(); |
| 319 | +
|
| 320 | + return "Kerberos " + Convert.ToBase64String(token_a); |
| 321 | +} |
| 322 | +"@ |
| 323 | + |
| 324 | +Add-Type -MemberDefinition $Signature -Name WindowsAuthentication -Namespace Secure32 |
| 325 | + [Secure32.WindowsAuthentication]::GetToken($PN) |
| 326 | +} |
| 327 | + |
| 328 | +#if the server certificate is self signed we need set Powershell to skip SSL certificate checks |
| 329 | +add-type @" |
| 330 | + using System.Net; |
| 331 | + using System.Security.Cryptography.X509Certificates; |
| 332 | + public class TrustAllCertsPolicy : ICertificatePolicy { |
| 333 | + public bool CheckValidationResult( |
| 334 | + ServicePoint srvPoint, X509Certificate certificate, |
| 335 | + WebRequest request, int certificateProblem) { |
| 336 | + return true; |
| 337 | + } |
| 338 | + } |
| 339 | +"@ |
| 340 | +[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy |
| 341 | + |
| 342 | + |
| 343 | + |
| 344 | + |
| 345 | +$PrincipleName = ""; |
| 346 | + |
| 347 | +#The first request is needed to retrieve the principle name. It can be skipped if you already know it. |
| 348 | +try |
| 349 | +{ |
| 350 | + Invoke-WebRequest -Uri ('https://'+$serverUrl+':52311/api/login') -Headers @{'PrincipalName' = ''} |
| 351 | +} |
| 352 | +catch [System.Net.WebException] |
| 353 | +{ |
| 354 | + if($_.Exception.Response.StatusCode.value__ -and $_.Exception.Response.StatusCode.value__ -eq 401){ |
| 355 | + |
| 356 | + $PrincipleName = $_.Exception.Response.Headers['PrincipalName'] |
| 357 | + #The returned token from GetBigFixToken is already in the requested form "Kerberos <token value>" |
| 358 | + $token = GetBigFixToken $PrincipleName |
| 359 | + |
| 360 | + #You can ask for a session token using the login api or you can ask directly other information |
| 361 | + # example: Invoke-WebRequest -Uri 'http://localhost:52311/api/sites' -Headers @{'Authorization' = $token} |
| 362 | + $response = Invoke-WebRequest -Uri ('https://'+$serverUrl+':52311/api/login') -Headers @{'Authorization' = $token} |
| 363 | + |
| 364 | + if( $response.StatusCode -eq 200){ |
| 365 | + Write-Output "Login successful. Session Token received." |
| 366 | + #We should now keep the session token returned and use it in the next requests |
| 367 | + #Write-Output ("{0} {1}" -f 'SessionToken: ', $response.Headers["SessionToken"]) |
| 368 | + #Invoke-WebRequest -Uri ('https://'+$serverUrl+':52311/api/sites') -Headers @{'SessionToken' = $response.Headers["SessionToken"]} -OutFile ./result.xml |
| 369 | + |
| 370 | + } |
| 371 | + else { |
| 372 | + Write-Output ("Unable to complete login.") |
| 373 | + } |
| 374 | + } |
| 375 | + else{ |
| 376 | + Write-Output ("Something went wrong contacting the BigFix Server $serverUrl.") |
| 377 | + } |
| 378 | +} |
| 379 | + |
| 380 | + |
| 381 | + |
0 commit comments