• Direct Access status Always "Connecting" on Windows 8

    Have you ever had experience about this issue?

    I deployed some Direct Access and I've got several problem with this technology, may be "Connecting" issue is the most headache problem.

    There are many causes can involve this behavior I will talk about two causes.

     

    First cause with IP-HTTPS error code 0x2AF9

    Status Connecting and Direct Access does not working

    If you run netsh by command promps on Windows Client: netsh interface httpstunnel show interface and get the follow message:

    Interface IPHTTPSInterface (Group Policy)  Parameters
    ————————————————————
    Role                       : client
    URL                        : https://directaccess.yourdomain.com:443/IPHTTPS
    Last Error Code            : 0x2af9
    Interface Status           : failed to connect to the IPHTTPS server

    then you can must check DNS name resolution and client PROXY configuration.

    If those following statement ore true:

    1. correctly resolve URL directaccess.yourdomain.com
    2. don't need proxy and proxy configuration is disabled
    3. firewall, between your client and directaccess server is correctly configured

    then your should check this registry key: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\iphlpsvc\Parameters\ProxyMgrIf, if you can see any sub-Keys below ProxyMgrIf key then delete the whole ProxyMgrIf key and restart your DirectAccess client.

    Second cause

    Status Connecting and Direct Access does working

    Check your company DNS server zone for Directaccess-WebProbeHost.yourcompany.local entry and if it missing then create the entry with DirectAccess server internal IP (use VIP if you have NLB)

    Read more: Cannot Reach the DirectAccess Server with IP-HTTPS (http://technet.microsoft.com/en-us/library/ee844126(v=ws.10).aspx)

  • DirectAccess and get website by internal proxy

    I have some clients must use internal proxy to access to some websites (security rules).

    When they use DirectAccess client outside corporate network, they have problem to access to those websites.

    If you are in the same situation, How can you resolve it?

     

    You need to edit Name Resolution Policy Table (NRPT) on DirectAccess (DA) server by using powershell cmdlet.

    Add-DAClientDNSConfiguration -DnsSuffix ‘www.mywebsite.com’ –proxyserver ‘myproxy.mydomain.com:8080’


    Powershell cmdlet will edit GPO DirectAccess policy, so after successfully run cmdlet you need to run GPUPDATE /FORCE on Windows 8 client to get effect immediatly.

     

    You can check NRPT table by command line:

     

    Windows 7:

    netsh namespace show policy

     

    Windows 8

    Get-DAEntryPointTableItem

     

     

    If you need to access to public URL by corporate network, then you need to configure name resolution in this way on your DirectAccess server:

     

     

    Read more: Add-DAClientDnsConfiguration (http://technet.microsoft.com/en-us/library/hh918437.aspx )

  • Come scrivere nell'event log da C++

    Ultimamente ero alle prese con un nuovo progetto nel quale ho sviluppato un componente per il NAP di Windows in linguaggio C++.

    Quando ho iniziato a cimentarmi a scrivere all'interno degli eventi di Windows, ho tristemente scoperto che non era così semplice come avviene in managed code (per esempio C#).

    In questo link viene spiegato in modo molto semplice come si scrive negli eventi di Windows utilizzando C++ unmanaged code, io cercherò di aggiungere qualche info in più per facilitare la comprensione di questo argomento.

    http://msdn.microsoft.com/en-us/library/windows/desktop/aa363680(v=vs.85).aspx

    L'approccio di base è il seguente:

    1. Definizione di tutti gli eventi all'interno di una DLL;
    2. Registrazione del provider degli aventi nel registro di sistema;
    3. Invocazione degli eventi dal programma (Esempio di utilizzo).

    1. Definizione di tutti gli eventi all'interno di una DLL

    Per definire gli eventi in una DLL partiamo da un file di testo dove elenchiamo gli eventi da creare in un formato ben preciso, e salvare questo file con nome MYEVENTPROVIDER:MC, ecco un esempio:


    ; // MyEventProvider.mc

    ; // This is the header section.


    SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS
                   Informational=0x1:STATUS_SEVERITY_INFORMATIONAL
                   Warning=0x2:STATUS_SEVERITY_WARNING
                   Error=0x3:STATUS_SEVERITY_ERROR
                  )


    FacilityNames=(System=0x0:FACILITY_SYSTEM
                   Runtime=0x2:FACILITY_RUNTIME
                   Stubs=0x3:FACILITY_STUBS
                   Io=0x4:FACILITY_IO_ERROR_CODE
                  )

    LanguageNames=(English=0x409:MSG00409)


    ; // The following are the categories of events.

    MessageIdTypedef=WORD

    MessageId=0x1
    SymbolicName=NETWORK_CATEGORY
    Language=English
    Network Events
    .

    MessageId=0x2
    SymbolicName=DATABASE_CATEGORY
    Language=English
    Database Events
    .

    MessageId=0x3
    SymbolicName=UI_CATEGORY
    Language=English
    UI Events
    .


    ; // The following are the message definitions.

    MessageIdTypedef=DWORD

    MessageId=0x100
    Severity=Error
    Facility=Runtime
    SymbolicName=MSG_INVALID_COMMAND
    Language=English
    The command is not valid.
    .


    MessageId=0x101
    Severity=Error
    Facility=System
    SymbolicName=MSG_BAD_FILE_CONTENTS
    Language=English
    File %1 contains content that is not valid.
    .

    MessageId=0x102
    Severity=Warning
    Facility=System
    SymbolicName=MSG_RETRIES
    Language=English
    There have been %1 retries with %2 success! Disconnect from
    the server and try again later.
    .

    MessageId=0x103
    Severity=Informational
    Facility=System
    SymbolicName=MSG_COMPUTE_CONVERSION
    Language=English
    %1 %%4096 = %2 %%4097.
    .


    ; // The following are the parameter strings */


    MessageId=0x1000
    Severity=Success
    Facility=System
    SymbolicName=QUARTS_UNITS
    Language=English
    quarts%0
    .

    MessageId=0x1001
    Severity=Success
    Facility=System
    SymbolicName=GALLONS_UNITS
    Language=English
    gallons%0
    .


    ATTENZIONE: Il punto definisce la fine del messaggio o della categoria definita.

    E' possibile definire più linguaggi e di conseguenza definire i messaggi nelle varie lingue, ogni messaggio contiene una SEVERITY, FACILITY, SYMBOLICNAME (che  è l'identificativo che andremo ad utilizzare per scrivere il messaggio nel log degli eventi), LANGUAGE e infine il messaggio stesso che può contenere dei parametri %1 %2 e così via.

    Una volta scritto il file con la definizione degli eventi, dobbiamo generare la DLL e l'header file che utilizzeremo nel nostro progetto.

    Per compilare il file, abbiamo bisogno di tre comandi: mc.exe, rc.exe e link.exe

    I primi due sono presenti all'interno del Windows SDK mentre il terzo all'interno di visual studio.

    Eseguire i comandi nel seguente ordine:

    mc -U myeventprovider.mc

    Compilare il file di risorse generato dal comando precedente:

    rc myeventprovider.rc

    Creare la DLL a partire dal file di risorse generato dal comando precedente (il parametro noentry è necessario).

    link -dll -noentry myeventprovider.res

    Il seguente è il file di header che va incluso nel progetto. Da notare all'interno del file gli identificativi dei messaggi.


    // MyEventProvider.mc
    // This is the header section.
    // The following are categories of events.
    //
    // Values are 32 bit values laid out as follows:
    //
    // 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
    // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
    // +---+-+-+-----------------------+-------------------------------+
    // |Sev|C|R| Facility | Code |
    // +---+-+-+-----------------------+-------------------------------+
    //
    // where
    //
    // Sev - is the severity code
    //
    // 00 - Success
    // 01 - Informational
    // 10 - Warning
    // 11 - Error
    //
    // C - is the Customer code flag
    //
    // R - is a reserved bit
    //
    // Facility - is the facility code
    //
    // Code - is the facility's status code
    //
    //
    // Define the facility codes
    //
    #define FACILITY_SYSTEM                  0x0
    #define FACILITY_STUBS                   0x3
    #define FACILITY_RUNTIME                 0x2
    #define FACILITY_IO_ERROR_CODE           0x4


    //
    // Define the severity codes
    //
    #define STATUS_SEVERITY_WARNING          0x2
    #define STATUS_SEVERITY_SUCCESS          0x0
    #define STATUS_SEVERITY_INFORMATIONAL    0x1
    #define STATUS_SEVERITY_ERROR            0x3


    //
    // MessageId: NETWORK_CATEGORY
    //
    // MessageText:
    //
    // Network Events
    //
    #define NETWORK_CATEGORY                 ((WORD)0x00000001L)

    //
    // MessageId: DATABASE_CATEGORY
    //
    // MessageText:
    //
    // Database Events
    //
    #define DATABASE_CATEGORY                ((WORD)0x00000002L)

    //
    // MessageId: UI_CATEGORY
    //
    // MessageText:
    //
    // UI Events
    //
    #define UI_CATEGORY                      ((WORD)0x00000003L)

    // The following are message definitions.
    //
    // MessageId: MSG_INVALID_COMMAND
    //
    // MessageText:
    //
    // The command is not valid.
    //
    #define MSG_INVALID_COMMAND              ((DWORD)0xC0020100L)

    //
    // MessageId: MSG_BAD_FILE_CONTENTS
    //
    // MessageText:
    //
    // File %1 contains content that is not valid.
    //
    #define MSG_BAD_FILE_CONTENTS            ((DWORD)0xC0000101L)

    //
    // MessageId: MSG_RETRIES
    //
    // MessageText:
    //
    // There have been %1 retries with %2 success! Disconnect from
    // the server and try again later.
    //
    #define MSG_RETRIES                      ((DWORD)0x80000102L)

    //
    // MessageId: MSG_COMPUTE_CONVERSION
    //
    // MessageText:
    //
    // %1 %%4096 = %2 %%4097.
    //
    #define MSG_COMPUTE_CONVERSION           ((DWORD)0x40000103L)

    // The following are the parameter strings */
    //
    // MessageId: QUARTS_UNITS
    //
    // MessageText:
    //
    // quarts%0
    //
    #define QUARTS_UNITS                     ((DWORD)0x00001000L)

    //
    // MessageId: GALLONS_UNITS
    //
    // MessageText:
    //
    // gallons%0
    //
    #define GALLONS_UNITS                    ((DWORD)0x00001001L)


    2. Registrazione del provider degli aventi nel registro di sistema

    Per registrare "MyEventProvider" come source event, modificare il registro del sistema manualmente, in particolare:

    • Se si vuole scrivere gli eventi nell'application log, utilizzare questa chiave: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\Application
    • Se si vuole scrivere gli eventi in un log personalizzato, allora utilizzare questa chiave: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\MyAppLog (MyAppLog deve essere creata manualmente)

    La seguente tabella mostra i valori da inserire nelle varie chiavi da creare:

    Value nameTypeValue dataCommento
    CategoryCount REG_DWORD 0x00000003 Indicare il numero di elementi definiti come categorie all'interno del file di definizione
    CategoryMessageFile REG_SZ path\MyEventProvider.dll Indicare il path e nome della DLL da registrare e che contiene la definizione degli eventi
    EventMessageFile REG_SZ path\MyEventProvider.dll Indicare il path e nome della DLL da registrare e che contiene la definizione degli eventi
    ParameterMessageFile REG_SZ path\MyEventProvider.dll Indicare il path e nome della DLL da registrare e che contiene la definizione degli eventi
    TypesSupported REG_DWORD 0x00000007

    Questo numero normalmente i tipi di eventi ecco il bitmask:

    • EVENTLOG_AUDIT_FAILURE (0x0010)
    • EVENTLOG_AUDIT_SUCCESS (0x0008)
    • EVENTLOG_ERROR_TYPE (0x0001)
    • EVENTLOG_INFORMATION_TYPE (0x0004)
    • EVENTLOG_WARNING_TYPE (0x0002)

    3. Invocazione degli eventi dal programma (Esempio di utilizzo)

    Una volta compilata la DLL e registrata nel registro di sistema, possiamo testare il tutto creando una funzione che ci semplifichi la scrittura del codice.

    La seguente è una funzione di esempio che ho creato e che è possibile utilizzare nel proprio codice.


    #include "stdafx.h"

    #include <windows.h>

    #include "MyEventProvider.h" // Questo include è fondamentale per riconoscere i MessageId, è l'header generato durante la compilazione della DLL */

    #define PROVIDER_NAME L"MyProvider" // Questo è il nome dato al nostro event provider, è possibile cambiarlo*/

     

    int WriteLog(DWORD Type, WORD Category, DWORD Msg, int Dim, LPCWSTR* Param)

    {

    int err = 0;

    HANDLE hEventLog = NULL;

    // The source name (provider) must exist as a subkey of Application.

    hEventLog = RegisterEventSource(NULL, PROVIDER_NAME);

    if (NULL == hEventLog)

    {

    err = GetLastError();

    goto cleanup;

    }

    // This event includes user-defined data as part of the event. The event message

    // does not use insert strings.

    if (!ReportEvent(hEventLog, Type, Category, Msg, NULL, Dim, 0, Param, NULL))

    {

    err = GetLastError();

    goto cleanup;

    }

    cleanup:

    if (hEventLog)

    DeregisterEventSource(hEventLog);

    return err;

    }


    Per testare il codice, creare un progetto C++, per esempio console application:

    1. Inserire l'include della definizione degli eventi: #include "MyEventProvider.h"
    2. Inserire il prototipo della funzione: int WriteLog(DWORD, WORD, DWORD, int, LPCWSTR*);
    3. Invocare la funzione nel seguente modo:

    // This event uses insert strings.

    pInsertStrings[0] = L"3";

    pInsertStrings[1] = L"0";

    if (WriteLog(EVENTLOG_WARNING_TYPE, NETWORK_CATEGORY, MSG_RETRIES, 2, (LPCWSTR*)pInsertStrings) != 0)

    {

    wprintf(L"ReportEvent failed with 0x%x for event 0x%x.\n", GetLastError(), MSG_RETRIES);

    }

    Con questo esempio si scrive un evento di warning di categoria Network Events, con messaggio There have been 3 retries with 0 success! Disconnect from
    the server and try again later.

  • How to move whole OU subtree bringing GPO and GPO link from source forest to destination forest

    During a Forest and Domain consolidation project I had a challenge to migrate users e computers between Forests.

    I had the need to maintain the same GPO and the same structure of OU.

    I dug the net and could not find anything that I could meet, I had to assemble various scripts, but even so I would not have satisfied my need.

    I wrote a powershell script that apply to this scenario.

    I'm still working on it, but I decided to share and hope to get some feedback for improving it or correct some bugs.

    This script  on target forest, create same source OU subtree, copy and link same source GPO on relative copied OU.

    WMIFilter is not migrated in this script version.

    Prerequisite:

    • Tested with Windows 2012 R2 (target) and Windows 2008 R2 (source)
    • RSAT
    • GPMC console
    • Tested with bidirectional Trust

    These are the parameters:

    • BaseSourceDN: DN of source OU subtree you want move
    • BaseTargetDN: DN of targetOU where you want move in
    • SourceDomain: source domain name
    • TargetDomainController: target domain controller server name
    • prefix: (optional) prefix name for target GPO

    # Sample .\move_OU1.ps1 -BaseSourceDN "OU=users,DC=contoso,DC=local" -BaseTargetDN "OU=users,OU=home,DC=adatum,DC=local" -SourceDomain "contoso.local" -TargetDomainController dc01.adatum.local -prefix "Contoso-"

    Param(

    [string]$BaseSourceDN,

    [string]$BaseTargetDN,

    [string]$SourceDomain,

    [string]$TargetDomainController,

    [string]$Prefix=""

    )

    function CopyGPO

    {

    param([string]$SourceDomain,

    [string]$TargetDomainController,

    [string]$SourceDN,

    [string]$OUTargetUrl)

    $oSourceOU=[adsi]"LDAP://$SourceDN"

    $gPLinks=$oSourceOU.gPLink

    if(($gPLinks -ne $null) -or ($gPLinks -ne ''))

    {

    $gPlink=$gPlinks.split('][')

    for ($i=$gPlink.count-2;$i -gt 0;$i=$i-2)

    {

    $GPO_URI=$gPlink[$i].split(';')

    $GPO_DN=$GPO_URI[0].substring(7)

    switch($GPO_URI[1])

    {

    "1" {$EnableStatus = 'No'; $EnforceStatus = 'No'}

    "2" {$EnableStatus = 'Yes'; $EnforceStatus = 'Yes'}

    "3" {$EnableStatus = 'No'; $EnforceStatus = 'Yes'}

    "0" {$EnableStatus = 'Yes'; $EnforceStatus = 'No'}

    }

    $GPO_URI_wDomain="LDAP://$SourceDomain/$GPO_DN"

    $oGPO=[adsi]"$GPO_URI_wDomain"

    $GPO_Name=$oGPO.DisplayName

    try

    {

    Write-Host

    Write-Host "Try to copy GPO $GPO_Name" -ForegroundColor Green

    Copy-GPO -SourceName "$GPO_Name" -SourceDomain "$SourceDomain" -TargetName "$Prefix$GPO_Name" -TargetDomainController "$TargetDomainController" -ErrorAction Stop

    $cGPOApply=$oGPO.psbase.objectsecurity.access |?{$_.ActivedirectoryRights -eq 'ExtendedRight'}

    Set-GPPermission -Name "$Prefix$GPO_Name" -TargetName "Authenticated Users" -PermissionLevel None -TargetType Group -ErrorAction SilentlyContinue

    foreach($GPOApply in $cGPOApply)

    {

    $SecurityFiltering=$GPOApply.IdentityReference

    Set-GPPermission -Name "$Prefix$GPO_Name" -TargetName "$SecurityFiltering" -PermissionLevel GpoApply -Server "$TargetDomainController" -TargetType Group -ErrorAction SilentlyContinue

    }

    if ($Prefix -eq '')

    {

    Write-Host "$GPO_Name copied" -ForegroundColor Green

    }

    else

    {

    Write-Host "$GPO_Name copied and renamed in $Prefix$GPO_Name" -ForegroundColor Green

    }

    }

    catch [exception]

    {

    write-host $_.Exception.Message -ForegroundColor Red

    }

    try

    {

    Write-Host

    Write-Host "Try to create link for GPO:$Prefix$GPO_Name on OU:$OUTargetUrl" -ForegroundColor Green

    New-GPLink -Name "$Prefix$GPO_Name" -Target $OUTargetUrl -Server "$TargetDomainController" -LinkEnabled $EnableStatus -Enforced $EnforceStatus -ErrorAction Stop

    Write-Host "Link for GPO:$Prefix$GPO_Name on OU:$OUTargetUrl created" -ForegroundColor Green

    }

    catch [Exception]{

    write-host $_.Exception.Message -ForegroundColor Red

    }

    }

    return

    }

    }

     

     

    function CreateOU

    {

    param ([string]$SourceDN,

    [string]$TargetDN)

    $oSourceOU=[adsi]"LDAP://$SourceDN"

    $RDN=[string]$oSourceOU.Name

    try

    {

    Write-Host

    Write-Host "Try to create OU=$RDN,$TargetDN" -ForegroundColor Green

    New-ADOrganizationalUnit -Name $RDN -Path $TargetDN

    Write-Host "OU=$RDN,$TargetDN created" -ForegroundColor Green

    $gPOption=$oSourceOU.gPOptions

    # Check if Blocked Inheritance is true

    if($gPOption -eq 1){

    Write-Host

    Write-Host "Try to set Block Inheritance true" -ForegroundColor Green

    Set-GPInheritance -IsBlocked Yes -Target "OU=$RDN,$TargetDN" # Block Inheritance

    Write-Host "Block Inheritance is true" -ForegroundColor Green

    }

    }

    catch [Exception]{

    write-host $_.Exception.ServerErrorMessage -ForegroundColor Red

    }

    $NewTargetDN="OU=$RDN,$TargetDN"

    $NewSourceDN=$SourceDN

    CopyGPO $SourceDomain $TargetDomainController $SourceDN $NewTargetDN

    $cOUs=$oSourceOU.Children | Where-Object{$_.schemaclassname -eq "OrganizationalUnit"}

    if (($cOUs -ne '') -and ($cOUs.count -ne 0))

    {

    foreach($ChildOU in $cOUs)

    {

    $RDN=[string]$ChildOU.name

    $NewSourceDN="OU=$RDN,"+$SourceDN

    CreateOU $NewSourceDN $NewTargetDN

    }

    }

    return

    }

     

    if(($BaseSourceDN -eq '') -or (!$BaseSourceDN) -or ($BaseTargetDN -eq '') -or (!$BaseTargetDN) -or

    ($SourceDomain -eq '') -or (!$SourceDomain) -or ($TargetDomainController -eq '') -or (!$TargetDomainController))

    {

    Write-Host "Incomplete parameters" -ForegroundColor Blue

    Write-Host "Use this sintax:"-ForegroundColor Blue

    Write-Host ".\move-ou.ps1 -BaseSourceDN ""OU=users,DC=contoso,DC=local"" -BaseTargetDN ""OU=users,OU=home,DC=adatum,DC=local"" -SourceDomain ""contoso.local"" -TargetDomainController ""dc01.adatum.local""" -ForegroundColor Blue

    }

    else

    {

    CreateOU $BaseSourceDN $BaseTargetDN

    }

  • How to add second user to Windows User Local Profile

    ATTENTION: this procedure could be not supported, then If you modify registry entry, you are doing at your own risk.
    When I afford a domain consolidation and than a Windows migration, many times I got request from clients to allow new migrated user (second user) to allow access to previous Windows User Local Profile.
    Normally I get this gol by ADMT, when I do Security Translation I use ADD mode on User Profile, but some clients asked me to do it without ADMT and just use a script.
    I did reverse engineering about ADMT and I found these steps.
    Assume Windows Operating System is Windows 7 and source user is sourcedomain\j9999 and target user is targetdomain\j9999
    1. Logon on workstation with sourcedomain\j9999 user
    2. Browse c:\users directory and find user profile folder j9999 and click right click on Properties
    3. Then click on Security Tab and then on Advanced button
    4. Add full control to user targetdomain\j9999 and apply to Replace all child object permission…
    5. Open regedit and select HKEY_CURRENT_USER

    6. Right click on Permission and add full control to user targetdomain\j9999
    7. Logoff and logon with local administrator user, or runas regedit with different user
    8. Copy the follow Registry Key changing these parameters:

    a. Insert Registry Key name with targetdomain\j9999 SID (string format)

    b. Copy same old profile registry entry

    c. Change only Sid  entry with binary hex targetdomain\j9999 user

       

    Log off and logon with both users (source and target) to check u r accessing to same Windows Local User Profile.

    Next step I would like to script the previous steps.