Class: LiveIdentity::Identity

Inherits:
Object
  • Object
show all
Defined in:
lib/live_identity.rb

Defined Under Namespace

Classes: ExtendedError, Service

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(memberName, flags) ⇒ Identity

Returns a new instance of Identity.

Raises:



213
214
215
216
217
218
219
220
221
222
# File 'lib/live_identity.rb', line 213

def initialize(memberName, flags)
    @hIdentity = nil
    wszMemberName = StringToWSTR(memberName)
    dwflags = flags
    pihIdentity = FFI::MemoryPointer.new(:PassportIdentityHandlePointer)
    hr = IDCRL.CreateIdentityHandle(wszMemberName, dwflags, pihIdentity)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    @hIdentity = pihIdentity.read_ulong
    ObjectSpace.define_finalizer(self, self.class.finalize(@hIdentity))
end

Instance Attribute Details

#hIdentityObject (readonly)

Returns the value of attribute hIdentity.



212
213
214
# File 'lib/live_identity.rb', line 212

def hIdentity
  @hIdentity
end

Class Method Details

.finalize(hIdentity) ⇒ Object



224
225
226
227
228
229
# File 'lib/live_identity.rb', line 224

def self.finalize(hIdentity)
    Proc.new do
        hr = IDCRL.CloseIdentityHandle(hIdentity)
        raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    end
end

Instance Method Details

#Authenticate(authPolicy, authFlags) ⇒ Object



480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
# File 'lib/live_identity.rb', line 480

def Authenticate(authPolicy, authFlags)
    done = false
    SetCallback() do |identity, data, canContinue|
        done = true
        0
    end
    begin
        LogonIdentityEx(authPolicy, authFlags)
    rescue LiveIdentityError
        state = GetAuthState()
        puts state
        CancelPendingRequest()
        puts GetExtendedError() if WinCommon::Errors::HRESULT::Equal?(state.RequestStatus, IDCRL::HRESULT::PPCRL_REQUEST_E_AUTH_SERVER_ERROR)
        raise
    end
    LiveIdentity::waitFor(Proc.new {done}, 'Authentication Timeout!') { CancelPendingRequest() }
    state = GetAuthState()
    if !state.IsAuthenticated?
        puts state
        CancelPendingRequest()
        puts GetExtendedError() if WinCommon::Errors::HRESULT::Equal?(state.RequestStatus, IDCRL::HRESULT::PPCRL_REQUEST_E_AUTH_SERVER_ERROR)
        raise LiveIdentityError.new(state.RequestStatus) if LiveIdentity::IsError?(state.RequestStatus)
        raise LiveIdentityError.new(state.AuthState)
    end
ensure
    SetCallback()
end

#AuthToService(target, policy = 'HBI', flags = :SERVICE_TOKEN_FROM_CACHE, sessionKey = false) ⇒ Object

Raises:



255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
# File 'lib/live_identity.rb', line 255

def AuthToService(target, policy = 'HBI', flags = :SERVICE_TOKEN_FROM_CACHE, sessionKey = false)
    szServiceTarget = StringToWSTR(target.to_s)
    szServicePolicy = StringToWSTR(policy.to_s)
    dwTokenRequestFlags = flags
    szToken = FFI::MemoryPointer.new(:PLPWSTR)
    pdwResultFlags = FFI::MemoryPointer.new(:PDWORD)
    ppbSessionKey = nil
    pcbSessionKeyLength = nil
    if sessionKey
        ppbSessionKey = FFI::MemoryPointer.new(:PPBYTE)
        pcbSessionKeyLength = FFI::MemoryPointer.new(:PDWORD)
    end
    hr = IDCRL.AuthIdentityToService(@hIdentity, szServiceTarget, szServicePolicy, dwTokenRequestFlags, szToken, pdwResultFlags, ppbSessionKey, pcbSessionKeyLength)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    authState = IDCRL::AuthState.new
    authState[:szToken] = szToken.read_pointer
    authState[:dwResultFlags] = pdwResultFlags.read_uint
    authState[:pbSessionKey] = ppbSessionKey.read_pointer if sessionKey
    authState[:dwSessionKeyLength] = pcbSessionKeyLength.read_uint if sessionKey
    authState.Token()
    authState.SessionKey()
    LiveIdentity::FreeMemory(szToken.read_pointer)
    LiveIdentity::FreeMemory(ppbSessionKey.read_pointer) if sessionKey
    authState
end

#AuthToServiceEx(requestFlags, rstParams) ⇒ Object

Raises:



365
366
367
368
369
370
371
# File 'lib/live_identity.rb', line 365

def AuthToServiceEx(requestFlags, rstParams)
    swRequestFlags = requestFlags
    dwpcRSTParamsCount = rstParams.count
    pcRSTParams = LiveIdentity::processRSTParams(rstParams)
    hr = IDCRL.AuthIdentityToServiceEx(@hIdentity, swRequestFlags, pcRSTParams, dwpcRSTParamsCount)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
end

#CancelPendingRequestObject

Raises:



394
395
396
397
# File 'lib/live_identity.rb', line 394

def CancelPendingRequest()
    hr = IDCRL.CancelPendingRequest(@hIdentity)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
end

#DecryptWithSessionKey(serviceName, algIdEncrypt, algIdHash, cipher) ⇒ Object

Raises:



445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
# File 'lib/live_identity.rb', line 445

def DecryptWithSessionKey(serviceName, algIdEncrypt, algIdHash, cipher)
    wszServiceName = StringToWSTR(serviceName)
    dwAlgIdEncrypt = algIdEncrypt
    dwAlgIdHash    = algIdHash
    dwCipherSize   = cipher.bytesize
    pbCipher       = FFI::MemoryPointer.new(:LPVOID)
    pbCipher.write_string(cipher, dwCipherSize)
    pbData      = FFI::MemoryPointer.new(:LPVOID)
    pdwDataSize = FFI::MemoryPointer.new(:PDWORD)
    hr = IDCRL.DecryptWithSessionKey(@hIdentity, wszServiceName, dwAlgIdEncrypt, dwAlgIdHash, pbCipher, dwCipherSize, pbData, pdwDataSize)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    data = pbData.read_string(pdwDataSize.read_pointer.read_uint)
    LiveIdentity::FreeMemory(pbData.read_pointer)
    data
end

#EncryptWithSessionKey(serviceName, algIdEncrypt, algIdHash, data) ⇒ Object

Raises:



429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
# File 'lib/live_identity.rb', line 429

def EncryptWithSessionKey(serviceName, algIdEncrypt, algIdHash, data)
    wszServiceName = StringToWSTR(serviceName)
    dwAlgIdEncrypt = algIdEncrypt
    dwAlgIdHash    = algIdHash
    dwDataSize     = data.count
    pbData         = FFI::MemoryPointer.new(:LPVOID)
    pbData.write_string(data, dwDataSize)
    pbCipher  = FFI::MemoryPointer.new(:PBYTE)
    pdwCipherSize = FFI::MemoryPointer.new(:PDWORD)
    hr = IDCRL.EncryptWithSessionKey(@hIdentity, wszServiceName, dwAlgIdEncrypt, dwAlgIdHash, pbData, dwDataSize, pbCipher, pdwCipherSize)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    cipher = pbCipher.read_string(pdwCipherSize.read_pointer.read_uint)
    LiveIdentity::FreeMemory(pbCipher.read_pointer)
    cipher
end

#GetAuthStateObject

Raises:



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/live_identity.rb', line 293

def GetAuthState
    hrAuthState = FFI::MemoryPointer.new(:PHRESULT)
    hrAuthRequired = FFI::MemoryPointer.new(:PHRESULT)
    hrRequestStatus = FFI::MemoryPointer.new(:PHRESULT)
    wszWebFlowUrl = FFI::MemoryPointer.new(:LPWSTR)
    hr = IDCRL.GetAuthState(@hIdentity, hrAuthState, hrAuthRequired, hrRequestStatus, wszWebFlowUrl)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    status = IDCRL::IDCRL_STATUS_V1.new
    status[:hrAuthState] = hrAuthState.read_long
    status[:hrAuthRequired] = hrAuthRequired.read_long
    status[:hrRequestStatus] = hrRequestStatus.read_long
    status[:wszWebFlowUrl] = wszWebFlowUrl.read_pointer
    status.WebFlowUrl unless status[:wszWebFlowUrl].null?
    LiveIdentity::FreeMemory(status[:wszWebFlowUrl])
    status
end

#GetAuthStateEx(serviceTarget, status) ⇒ Object

Raises:



373
374
375
376
377
378
379
# File 'lib/live_identity.rb', line 373

def GetAuthStateEx(serviceTarget, status)
    wszServiceTarget = StringToWSTR(serviceTarget)
    hr = IDCRL.GetAuthStateEx(@hIdentity, wszServiceTarget, status[:hrAuthState], status[:hrAuthRequired], status[:hrRequestStatus], status[:wszWebFlowUrl])
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    status.WebFlowUrl
    LiveIdentity::FreeMemory(status[:wszWebFlowUrl])
end

#GetCertificate(rstParam, minTTL, requestFlags) ⇒ Object

Raises:



381
382
383
384
385
386
387
388
389
390
391
392
# File 'lib/live_identity.rb', line 381

def GetCertificate(rstParam, minTTL, requestFlags)
    pcRSTParams = IDCRL::RSTParams.build(rstParam)
    pdwMinTTL = FFI::MemoryPointer.new(:DWORD)
    pdwMinTTL.write_uint(minTTL)
    dwRequestFlags = requestFlags
    certSet = IDCRL::CertSet.build
    cbPOP = FFI::MemoryPointer.new(:DWORD)
    hr = IDCRL.GetCertificate(@hIdentity, pcRSTParams, pdwMinTTL, dwRequestFlags, certSet[:pCertContext], certSet[:pbPOP], cbPOP, certSet[:pCACertContext])
    certSet[:cbPOP] = cbPOP.read_uint
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    certSet
end

#GetExtendedErrorObject



461
462
463
# File 'lib/live_identity.rb', line 461

def GetExtendedError
    ExtendedError.new(self)
end

#GetProperty(property) ⇒ Object

Raises:



238
239
240
241
242
243
244
245
246
# File 'lib/live_identity.rb', line 238

def GetProperty(property)
    ipProperty = property
    pwszPropertyValue = FFI::MemoryPointer.new(:PLPWSTR)
    hr = IDCRL.GetIdentityProperty(@hIdentity, ipProperty, pwszPropertyValue)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    propertyValue = read_wide_string(pwszPropertyValue.read_pointer)
    LiveIdentity::FreeMemory(pwszPropertyValue.read_pointer)
    propertyValue
end

#GetPropertyByName(name) ⇒ Object

Raises:



399
400
401
402
403
404
405
406
407
# File 'lib/live_identity.rb', line 399

def GetPropertyByName(name)
    wszPropertyName = StringToWSTR(name)
    pwszPropertyValue = FFI::MemoryPointer.new(:pointer)
    hr = IDCRL.GetIdentityPropertyByName(@hIdentity, wszPropertyName, pwszPropertyValue)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    propertyValue = read_wide_string(pwszPropertyValue.read_pointer)
    LiveIdentity::FreeMemory(pwszPropertyValue.read_pointer)
    propertyValue
end

#GetService(target, policy = 'HBI', flags = :SERVICE_TOKEN_FROM_CACHE, sessionKey = false) ⇒ Object



508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
# File 'lib/live_identity.rb', line 508

def GetService(target, policy = 'HBI', flags = :SERVICE_TOKEN_FROM_CACHE, sessionKey = false)
    begin
        authState = AuthToService(target, policy, flags, sessionKey)
    rescue LiveIdentityError => e
        done = false
        SetCallback() do |identity, data, canContinue|
            done = true
            0
        end
        if WinCommon::Errors::HRESULT::Equal?(e.code, [IDCRL::HRESULT::PPCRL_E_BUSY, IDCRL::HRESULT::PPCRL_E_UNABLE_TO_RETRIEVE_SERVICE_TOKEN, IDCRL::HRESULT::PPCRL_REQUEST_E_FORCE_SIGNIN])
            authState = AuthToService(target, policy, :SERVICE_TOKEN_REQUEST_TYPE_NONE, sessionKey)
            LiveIdentity::waitFor(Proc.new {done}, 'Authorization Timeout!') { CancelPendingRequest() }
            state = GetAuthState()
            if !state.IsAuthenticated?
                puts state
                puts GetExtendedError() if WinCommon::Errors::HRESULT::Equal?(state.RequestStatus, IDCRL::HRESULT::PPCRL_REQUEST_E_AUTH_SERVER_ERROR)
                raise LiveIdentityError.new(state.RequestStatus) if LiveIdentity::IsError?(state.RequestStatus)
                raise LiveIdentityError.new(state.AuthState)
            end
        else
            raise
        end
    ensure
        SetCallback()
    end
    authState = AuthToService(target, policy, :SERVICE_TOKEN_FROM_CACHE, sessionKey) unless authState.Token()
    Service.new(authState)
end

#GetWebAuthUrl(targetServiceName, servicePolicy = 'HBI', additionalPostParams = nil, sourceServiceName = nil) ⇒ Object

Raises:



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/live_identity.rb', line 334

def GetWebAuthUrl(targetServiceName, servicePolicy = 'HBI', additionalPostParams = nil, sourceServiceName = nil)
    wszTargetServiceName = StringToWSTR(targetServiceName)
    wszServicePolicy = StringToWSTR(servicePolicy)
    wszAdditionalPostParams = nil
    wszAdditionalPostParams = StringToWSTR(additionalPostParams) if additionalPostParams
    wszSourceServiceName = nil
    wszSourceServiceName = StringToWSTR(sourceServiceName) if sourceServiceName
    pszMD5Url   = FFI::MemoryPointer.new(:PLPWSTR)
    pszPostData = FFI::MemoryPointer.new(:PLPWSTR)
    hr = IDCRL.GetWebAuthUrl(@hIdentity, wszTargetServiceName, wszServicePolicy, wszAdditionalPostParams, wszSourceServiceName, pszMD5Url, pszPostData)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    md5data = IDCRL::MD5Data.new
    md5data[:szMD5Url] = pszMD5Url.read_pointer
    md5data[:szPostData] = pszPostData.read_pointer
    md5data.MD5Url
    md5data.PostData
    LiveIdentity::FreeMemory(pszMD5Url.read_pointer)
    LiveIdentity::FreeMemory(pszPostData.read_pointer)
    md5data
end

#GetWebAuthUrlEx(webAuthFlag, targetServiceName, servicePolicy = 'HBI', additionalPostParams = nil) ⇒ Object

Raises:



409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
# File 'lib/live_identity.rb', line 409

def GetWebAuthUrlEx(webAuthFlag, targetServiceName, servicePolicy = 'HBI', additionalPostParams = nil)
    dwWebAuthFlag = webAuthFlag
    wszTargetServiceName = StringToWSTR(targetServiceName)
    wszServicePolicy = StringToWSTR(servicePolicy)
    wszAdditionalPostParams = nil
    wszAdditionalPostParams = StringToWSTR(additionalPostParams) if additionalPostParams
    pszSHA1Url      = FFI::MemoryPointer.new(:PLPWSTR)
    pszSHA1PostData = FFI::MemoryPointer.new(:PLPWSTR)
    hr = IDCRL.GetWebAuthUrlEx(@hIdentity, dwWebAuthFlag, wszTargetServiceName, wszServicePolicy, wszAdditionalPostParams, pszSHA1Url, pszSHA1PostData)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    sha1 = IDCRL::SHA1.new
    sha1[:szSHA1Url] = pszSHA1Url.read_pointer
    sha1[:szSHA1PostData] = pszSHA1PostData.read_pointer
    sha1.SHA1Url
    sha1.SHA1PostData
    LiveIdentity::FreeMemory(pszSHA1Url.read_pointer)
    LiveIdentity::FreeMemory(pszSHA1PostData.read_pointer)
    sha1
end

#HasPersistedCredential?(credType) ⇒ Boolean

Returns:

  • (Boolean)

Raises:



317
318
319
320
321
322
323
# File 'lib/live_identity.rb', line 317

def HasPersistedCredential?(credType)
    wszCredType = StringToWSTR(credType)
    lpbPersisted = FFI::MemoryPointer.new(:LONG)
    hr = IDCRL.HasPersistedCredential(@hIdentity, credType, lpbPersisted)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
    lpbPersisted.read_long == 0x00000001
end

#IsAuthenticated?Boolean

Returns:

  • (Boolean)


465
466
467
468
469
470
471
472
473
474
475
476
477
478
# File 'lib/live_identity.rb', line 465

def IsAuthenticated?
    state = GetAuthState()
    if !state.IsAuthenticated?
        if !WinCommon::Errors::HRESULT::Equal?(state.RequestStatus, [WinCommon::Errors::HRESULT::S_OK, IDCRL::HRESULT::PPCRL_AUTHREQUIRED_E_PASSWORD])
            puts GetExtendedError() if WinCommon::Errors::HRESULT::Equal?(state.RequestStatus, IDCRL::HRESULT::PPCRL_REQUEST_E_AUTH_SERVER_ERROR)
            raise LiveIdentityError.new(state.RequestStatus)
        end
        if !WinCommon::Errors::HRESULT::Equal?(state.AuthState, [WinCommon::Errors::HRESULT::S_OK, IDCRL::HRESULT::PPCRL_AUTHSTATE_E_UNAUTHENTICATED, IDCRL::HRESULT::PPCRL_AUTHSTATE_E_EXPIRED])
            raise LiveIdentityError.new(state.AuthState)
        end
        return false
    end
    true
end

#LogonIdentity(policy, authFlags) ⇒ Object

Raises:



310
311
312
313
314
315
# File 'lib/live_identity.rb', line 310

def LogonIdentity(policy, authFlags)
    wszPolicy = StringToWSTR(policy)
    dwAuthFlags = authFlags
    hr = IDCRL.LogonIdentity(@hIdentity, wszPolicy, dwAuthFlags)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
end

#LogonIdentityEx(authPolicy, authFlags, rstParams = []) ⇒ Object

Raises:



355
356
357
358
359
360
361
362
363
# File 'lib/live_identity.rb', line 355

def LogonIdentityEx(authPolicy, authFlags, rstParams = [])
    wszAuthPolicy = nil
    wszAuthPolicy = StringToWSTR(authPolicy) if authPolicy
    dwAuthFlags = authFlags
    dwpcRSTParamsCount = rstParams.count
    pcRSTParams = LiveIdentity::processRSTParams(rstParams)
    hr = IDCRL.LogonIdentityEx(@hIdentity, wszAuthPolicy, dwAuthFlags, pcRSTParams, dwpcRSTParamsCount)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
end

#PersistCredential(credType) ⇒ Object

Raises:



281
282
283
284
285
# File 'lib/live_identity.rb', line 281

def PersistCredential(credType)
    wszCredType = StringToWSTR(credType)
    hr = IDCRL.PersistCredential(@hIdentity, wszCredType)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
end

#RemovePersistedCredential(credType) ⇒ Object

Raises:



287
288
289
290
291
# File 'lib/live_identity.rb', line 287

def RemovePersistedCredential(credType)
    wszCredType = StringToWSTR(credType)
    hr = IDCRL.RemovePersistedCredential(@hIdentity, wszCredType)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
end

#SetCallback(callBackData = nil, &callBackFunction) ⇒ Object

Raises:



325
326
327
328
329
330
331
332
# File 'lib/live_identity.rb', line 325

def SetCallback(callBackData = nil, &callBackFunction)
    hr = IDCRL.SetIdentityCallback(@hIdentity, callBackFunction, callBackData)
    if WinCommon::Errors::HRESULT::Equal?(hr, IDCRL::HRESULT::PPCRL_E_BUSY)
        sleep(0.1)
        hr = IDCRL.SetIdentityCallback(@hIdentity, callBackFunction, callBackData)
    end
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
end

#SetCredential(type, value) ⇒ Object

Raises:



231
232
233
234
235
236
# File 'lib/live_identity.rb', line 231

def SetCredential(type, value)
    wszCredType = StringToWSTR(type)
    wszCredValue = StringToWSTR(value)
    hr = IDCRL.SetCredential(@hIdentity, wszCredType, wszCredValue)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
end

#SetProperty(property, value) ⇒ Object

Raises:



248
249
250
251
252
253
# File 'lib/live_identity.rb', line 248

def SetProperty(property, value)
    ipProperty = property
    wszPropertyValue = StringToWSTR(value)
    hr = IDCRL.SetIdentityProperty(@hIdentity, ipProperty, wszPropertyValue)
    raise LiveIdentityError.new(hr) if LiveIdentity::IsError?(hr)
end