<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; VB.NET: Авторизация OpenVPN через учётку Windows]]></title>
		<link>http://forum.script-coding.com/viewtopic.php?id=9001</link>
		<atom:link href="http://forum.script-coding.com/extern.php?action=feed&amp;tid=9001&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «VB.NET: Авторизация OpenVPN через учётку Windows».]]></description>
		<lastBuildDate>Wed, 18 Dec 2013 15:07:28 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: VB.NET: Авторизация OpenVPN через учётку Windows]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=78230#p78230</link>
			<description><![CDATA[<p>Немного расширил решение. Итого умеет:<br />1. Проверять пару логин-пароль.<br />2. Проверять нахождение пользователя в группе(непосредственно, без проверки вхождения через членство в других группах).<br />3. Работает для локальной авторизации и для домена(про домен - вроде работает, но мой комп не в домене и тест нельзя назвать полноценным).<br />4. Пишет лог(в файл).<br />5. Настройки берёт из INI-файла.</p><p>Пути сборок не сокращал <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" />.</p><p>Основной модуль:<br /></p><div class="codebox"><pre><code>
Module winauth
    Dim logfile As System.IO.StreamWriter
    Dim pwdfile As System.IO.StreamReader
    Dim INI As New Class_ini_ops
    Function Main(ByVal cmdArgs() As String) As Integer
        Dim oContext As System.DirectoryServices.AccountManagement.PrincipalContext
        Dim oGroupUsers As System.DirectoryServices.AccountManagement.GroupPrincipal
        Dim usrName As String
        Dim usrPass As String
        Dim returnValue As Boolean

        Dim ini_file = System.Environment.CurrentDirectory.ToString &amp; &quot;\&quot; &amp; &quot;config.ini&quot;
        Dim ini_section = &quot;Configuration&quot;

        &#039;chk ini file
        If INI.GetSectionParams(ini_file, ini_section) Is Nothing Then
            Echo(&quot;Incorrect INI format.&quot;)
            Return 1
        End If

        Dim GroupName As String
        GroupName = INI.GetParamValue(ini_file, ini_section, &quot;GroupName&quot;)
        If GroupName Is Nothing Then
            Echo(&quot;User target group not set in ini-file.&quot;)
            Return 1
        End If

        &#039;имя(и путь) файла вынести в конфиг
        logfile = My.Computer.FileSystem.OpenTextFileWriter(&quot;winauth.log&quot;, True, _
                                                    System.Text.Encoding.GetEncoding(1251))
        logfile.AutoFlush = True

        &#039;check args
        If cmdArgs.Count &lt;&gt; 1 Then
            Echo(&quot;Wrong parametrs.&quot;)
            Return 1
        Else
            Try
                pwdfile = My.Computer.FileSystem.OpenTextFileReader(cmdArgs(0).ToString, _
                                                    System.Text.Encoding.GetEncoding(1251))
            Catch ex As Exception
                Echo(ex.Message.ToString)
                Echo(&quot;pwdfile not found.&quot;)
            End Try

            Try
                usrName = pwdfile.ReadLine.ToString
            Catch ex As Exception
                Echo(ex.Message.ToString)
                Echo(&quot;No data in pwdfile.&quot;)
                Return 1
            End Try

            Try
                usrPass = pwdfile.ReadLine.ToString
            Catch ex As Exception
                Echo(ex.Message.ToString)
                Echo(&quot;No password in pwdfile.&quot;)
                Return 1
            End Try
        End If
        pwdfile.Close()

        &#039;Get Auth context from INI, default is Local
        Dim iniContext
        iniContext = INI.GetParamValue(ini_file, ini_section, &quot;Context&quot;)
        If iniContext Is Nothing Then
            iniContext = &quot;Local&quot;
        End If

        &#039; Set PrincipalContext
        Dim DN As String = &quot;&quot;
        Dim PDC As String = &quot;&quot;
        Select Case iniContext
            Case &quot;Local&quot;
                oContext = New System.DirectoryServices.AccountManagement.PrincipalContext( _
                            System.DirectoryServices.AccountManagement.ContextType.Machine, _
                            System.Environment.MachineName.ToString)
            Case &quot;Domain&quot;
                PDC = INI.GetParamValue(ini_file, ini_section, &quot;PDC&quot;)
                If PDC Is Nothing Then
                    Echo(&quot;PDC not set in ini-file.&quot;)
                    Return 1
                End If
                DN = INI.GetParamValue(ini_file, ini_section, &quot;DN&quot;)
                If DN Is Nothing Then
                    Echo(&quot;DN not set in ini-file.&quot;)
                    Return 1
                End If
                oContext = New System.DirectoryServices.AccountManagement.PrincipalContext( _
                                System.DirectoryServices.AccountManagement.ContextType.Domain, _
                                PDC, DN)
            Case Else
                Echo(&quot;Context not set in ini-file or incorrect.&quot;)
                Return 1
        End Select

        &#039;Check that the user is a member of the group
        oGroupUsers = System.DirectoryServices.AccountManagement.GroupPrincipal.FindByIdentity(oContext, _
                                DirectoryServices.AccountManagement.IdentityType.Name, _
                                GroupName)
        Dim oUsers As System.DirectoryServices.AccountManagement.PrincipalSearchResult(Of  _
                                        System.DirectoryServices.AccountManagement.Principal)
        oUsers = Nothing
        If oGroupUsers Is Nothing Then
            Echo(&quot;No such group [&quot; &amp; GroupName &amp; &quot;] found.&quot;)
            Return 1
        Else
            oUsers = oGroupUsers.GetMembers
        End If

        If oUsers.Contains(System.DirectoryServices.AccountManagement.Principal.FindByIdentity(oContext, usrName)) Then
            Debug.Print(&quot;caught!&quot;)
        Else
            Debug.Print(&quot;shot at milk...&quot;)
            Select Case iniContext
                Case &quot;Local&quot;
                    Echo(&quot;Group check failure: the user is not a member of [&quot; &amp; GroupName &amp; &quot;].&quot;)
                Case &quot;Domain&quot;
                    Echo(&quot;Group check failure: the user is not a member of [&quot; &amp; GroupName &amp; &quot;@{&quot; &amp; DN &amp; &quot;}].&quot;)
            End Select
            Return 1
        End If

        Try
            returnValue = oContext.ValidateCredentials(usrName, usrPass)
        Catch ex As Exception
            Echo(ex.Message.ToString)
            Return 1
            &#039;Error Codes list for Microsoft technologies:
            &#039;http://www.symantec.com/business/support/index?page=content&amp;id=TECH12638
            &#039;&quot;HRESULT: 0x80070533&quot; == &quot;Logon failure: account currently disabled.&quot;
        End Try

        Select Case returnValue
            Case False
                Echo(&quot;Logon failure: username or password incorrect.&quot;)
                Return 1
            Case True
                Echo(&quot;Logon is successful.&quot;)
                Return 0
            Case Else
                Echo(&quot;Unknown Error?&quot;)
                Return 1
        End Select
    End Function
    Sub Echo(ByVal text)
        Console.WriteLine(text)
        Debug.Print(text)
        logfile.WriteLine(Now() &amp; &quot;:&gt; &quot; &amp; text)
    End Sub
End Module
</code></pre></div><p>Клас для работы с INI:<br /></p><div class="codebox"><pre><code>
Public Class Class_ini_ops
    &#039;изначально была копипаста отсюда: http://www.cyberforum.ru/vb-net/thread382768.html
#Region &quot;API Calls&quot;
    Private Declare Unicode Function WritePrivateProfileString Lib &quot;kernel32&quot; _
    Alias &quot;WritePrivateProfileStringW&quot; (ByVal lpApplicationName As String, _
    ByVal lpKeyName As String, ByVal lpString As String, _
    ByVal lpFileName As String) As Integer

    Private Declare Unicode Function GetPrivateProfileString Lib &quot;kernel32&quot; _
    Alias &quot;GetPrivateProfileStringW&quot; (ByVal lpApplicationName As String, _
    ByVal lpKeyName As String, ByVal lpDefault As String, _
    ByVal lpReturnedString As String, ByVal nSize As Int32, _
    ByVal lpFileName As String) As Integer
#End Region
    ReadOnly CallBufferSize As Short = 4096
    Public Function GetSectionsList(ByVal INIfile As String) As Array
        Dim n As Integer
        Dim sData As String
        Dim sb As New System.Text.StringBuilder
        sData = sb.Insert(0, vbNullChar, CallBufferSize).ToString
        n = GetPrivateProfileString(vbNullString, vbNullString, vbNullString, sData, CallBufferSize, INIfile)
        If n &gt; 0 Then
            GetSectionsList = sData.Substring(0, n - 1).Split(vbNullChar)
        Else
            GetSectionsList = Nothing
        End If
    End Function
    Public Function GetSectionParams(ByVal INIfile As String, ByVal SectionName As String) As Array
        Dim n As Integer
        Dim sData As String
        Dim sb As New System.Text.StringBuilder
        sData = sb.Insert(0, vbNullChar, CallBufferSize).ToString
        n = GetPrivateProfileString(SectionName, vbNullString, vbNullString, sData, CallBufferSize, INIfile)
        If n &gt; 0 Then
            GetSectionParams = sData.Substring(0, n - 1).Split(vbNullChar)
        Else
            GetSectionParams = Nothing
        End If
    End Function
    Public Overloads Function GetParamValue(ByVal INIfile As String, ByVal SectionName As String, ByVal ParamName As String) As String
        Dim n As Integer
        Dim sData As String
        Dim sb As New System.Text.StringBuilder
        sData = sb.Insert(0, vbNullChar, CallBufferSize).ToString
        n = GetPrivateProfileString(SectionName, ParamName, vbNullString, sData, CallBufferSize, INIfile)
        If n &gt; 0 Then
            GetParamValue = sData.Substring(0, n)
        Else
            GetParamValue = Nothing
        End If
    End Function
    Public Overloads Function GetParamValue(ByVal INIfile As String, ByVal SectionName As String, ByVal ParamName As String, _
                                            ByVal DefaultValue As String) As String
        Dim n As Integer
        Dim sData As String
        Dim sb As New System.Text.StringBuilder
        sData = sb.Insert(0, vbNullChar, CallBufferSize).ToString
        n = GetPrivateProfileString(SectionName, ParamName, DefaultValue, sData, CallBufferSize, INIfile)
        If n &gt; 0 Then
            GetParamValue = sData.Substring(0, n)
        Else
            GetParamValue = Nothing
        End If
    End Function
    Public Function SetParamValue(ByVal INIfile As String, ByVal SectionName As String, ByVal ParamName As String, _
                                  ByVal ParamValue As String) As Boolean
        Call WritePrivateProfileString(SectionName, ParamName, ParamValue, INIfile)
        If ParamValue = GetParamValue(INIfile, SectionName, ParamName) Then
            SetParamValue = True
        Else
            SetParamValue = False
        End If
    End Function
End Class
</code></pre></div><p>Пример конфига(config.ini, ищется в папке в приложением):<br /></p><div class="codebox"><pre><code>
[Configuration]
;set auth context
;Local - check local credentials(default)
;Domain -  check credentials in Domain
Context = Local

; Used only in Context = Domain
PDC = MyServer
DN = &quot;DC=mydomain,DC=local&quot;

;target user group
GroupName = &quot;Операторы сервера&quot;
</code></pre></div><p>Стоит ли что-то ещё доделать дабы иметь полноценную заготовку под универсальное использование(или не универсальное - с доработкой напильником под конкретные хотелки)?<br />Понятное дело, под каждую задачу подстраиваться перебор, но что-то более менее законченное хотелось бы в коллекцию пускать.</p>]]></description>
			<author><![CDATA[null@example.com (BeS Yara)]]></author>
			<pubDate>Wed, 18 Dec 2013 15:07:28 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=78230#p78230</guid>
		</item>
		<item>
			<title><![CDATA[Re: VB.NET: Авторизация OpenVPN через учётку Windows]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=78052#p78052</link>
			<description><![CDATA[<div class="quotebox"><cite>greg zakharov пишет:</cite><blockquote><p>Вопрос напоследок: будет ли Ваш код в коллекции?</p></blockquote></div><p>Была мысль сразу опубликовать туда, но подумал что могут появиться вопросы и дополнения, и решил для начала поместить в обсуждения.<br />Хорошо бы дополнить код проверкой на вхождения пользователя в группы, возможно использованием конфигурационных файлов(ini или xml). Это придало бы некоторую законченность решению, тогда и в коллекцию можно <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" />.</p><p>В логгировании в системные журналы особого смысла не вижу, лог-файла достаточно.</p><p>P.S. можно ещё добавить действия при неоднократных неудачных попытках авторизации(например, блокировать IP через netsh - для RDP такой скриптик делал недавно), но это уже совсем специфично. Наиболее универсальный набор - проверка пароля, проверка группы, чтение конфига(здесь не скрипт, вполне востребовано).</p>]]></description>
			<author><![CDATA[null@example.com (BeS Yara)]]></author>
			<pubDate>Thu, 12 Dec 2013 06:25:08 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=78052#p78052</guid>
		</item>
		<item>
			<title><![CDATA[Re: VB.NET: Авторизация OpenVPN через учётку Windows]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=78049#p78049</link>
			<description><![CDATA[<p>Прошу прощения, ссылку как-то упустил из виду (должно быть сказывается недосыпание).<br /></p><div class="quotebox"><cite>BeS Yara пишет:</cite><blockquote><p>Собрать из консоли можно, но зачем? Всё равно отлаживать удобнее в студии, в особо запущенных случаях я и VBS в студию передаю для отдки .<br />Касательно сокращения - к VB.NET обращаюсь эпизодически, к коду могу вернуться через неделю, месяц, год. Мне проще будет вспомнить и разобраться по полным путям.</p></blockquote></div><p>У каждого свое представление об удобстве, и если Вам удобней использовать полные имена, то так тому и быть. А VB.NET лично я предпочитаю C# и IL, ровно как и V$ - Far и mdbg.<br /></p><div class="quotebox"><cite>Bes Yara пишет:</cite><blockquote><p>Мне тоже не нравится этот способ передачи паролей скрипту.</p></blockquote></div><p>Это уже вопрос касательно выдумки, а последняя приходит всегда неожиданно.<br /></p><div class="quotebox"><cite>Bes Yara пишет:</cite><blockquote><p>Ну и ACL никто не отменял, так же как и EFS...</p></blockquote></div><p>EFS - то еще зло. Но привести аргументы в пользу этого утверждения не позволяют правила форума (какбы намек на нечестивый код).<br />Вопрос напоследок: будет ли Ваш код в коллекции?</p>]]></description>
			<author><![CDATA[null@example.com (greg zakharov)]]></author>
			<pubDate>Thu, 12 Dec 2013 06:10:34 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=78049#p78049</guid>
		</item>
		<item>
			<title><![CDATA[Re: VB.NET: Авторизация OpenVPN через учётку Windows]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=78048#p78048</link>
			<description><![CDATA[<div class="quotebox"><cite>greg zakharov пишет:</cite><blockquote><p>Какбэ... а где vbs&#039;ка, с которой началось повествование? Взглянуть любопытно.</p></blockquote></div><p>Ссылка на код была в первом абзаце. Дублирую: https://sites.google.com/site/amigo4life2/openvpn<br />Мне кажется, там перемудрили - слишком много процедур(IMHO, необоснованно много), зачем-то INI-файл задействовали, хотя всё можно было указать в первых строках скрипта(там всего 4 параметра)... KISS отдыхает <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" />.</p><div class="quotebox"><cite>greg zakharov пишет:</cite><blockquote><p>Относительно кода. Собирать приложения .NET можно и без M$ V$ (csc /nologo /t:exe /out:MyApp.exe /optimize+ /debug:pdbonly /r:... source.cs), а сам код мог бы выглядеть несколько компактней, если бы Вы использовали Imports.</p></blockquote></div><p>Собрать из консоли <span class="bbu"><strong><a href="http://www.script-coding.com/DotNet/CmdLineCompiler.html">можно</a></strong></span>, но зачем? Всё равно отлаживать удобнее в студии, в особо запущенных случаях я и VBS в студию передаю для отдки <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" />.<br />Касательно сокращения - к VB.NET обращаюсь эпизодически, к коду могу вернуться через неделю, месяц, год. Мне проще будет вспомнить и разобраться по полным путям. А так, да - это сократило бы длины строк. Как минимум трёх из 67.</p><div class="quotebox"><cite>greg zakharov пишет:</cite><blockquote><p>Если по существу, то для разбора аргументов было бы удобней сделать отдельный класс, а вот пароль - не не хранить в текстовом файле в открытом виде.</p></blockquote></div><p>Тут 67 строк кода(с учётом переносов), и разбор аргументов выполняется один раз. Не вижу смысла выносить это не то что в клас - даже в отдельную процедуру.</p><p>По поводу паролей. Мне тоже не нравится этот способ передачи паролей скрипту. Но тут вопрос к комьюнити OpenVPN - механизм передачи пароля скрипту не я придумал. Полагаю, через параметры не стали передавать из-за сложностей с используемыми в пароле символами.<br />С другой стороны, файл существует только в период от передачи его имени скрипту до возврата скриптом кода выхода. Ну и ACL никто не отменял, так же как и EFS(если решим шифроваться и от прочих админов сервера, но это уже параноя).</p><p>По документации ещё упоминается передача пары логин-пароль через переменные окружения, но что-то не взлетело - то ли под win не работает, то ли лыжи не едут. Долго разбираться не стал, остановился на файле и ограничении доступа к папке с ним. В моём случае админ один и терминального использования сервера не предполагается, так что и этого должно хватить с огромным запасом.</p>]]></description>
			<author><![CDATA[null@example.com (BeS Yara)]]></author>
			<pubDate>Thu, 12 Dec 2013 05:22:13 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=78048#p78048</guid>
		</item>
		<item>
			<title><![CDATA[Re: VB.NET: Авторизация OpenVPN через учётку Windows]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=78028#p78028</link>
			<description><![CDATA[<p>Какбэ... а где vbs&#039;ка, с которой началось повествование? Взглянуть любопытно.<br />Относительно кода. Собирать приложения .NET можно и без M$ V$ (vbc /nologo /t:exe /out:MyApp.exe /optimize+ /debug:pdbonly /r:... *.vb), а сам код мог бы выглядеть несколько компактней, если бы Вы использовали Imports. Впрочем, это мелочи. Если по существу, то для разбора аргументов было бы удобней сделать отдельный класс, а вот пароль - не хранить в текстовом файле в открытом виде.</p>]]></description>
			<author><![CDATA[null@example.com (greg zakharov)]]></author>
			<pubDate>Wed, 11 Dec 2013 17:37:29 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=78028#p78028</guid>
		</item>
		<item>
			<title><![CDATA[VB.NET: Авторизация OpenVPN через учётку Windows]]></title>
			<link>http://forum.script-coding.com/viewtopic.php?pid=78012#p78012</link>
			<description><![CDATA[<p>Есть в природе OpenVPN, умеющий при авторизации пользователей запускать скрипт для дополнительной авторизации. Под линуксы скриптов навалом, под Windows&nbsp; нашел одну <a href="https://sites.google.com/site/amigo4life2/openvpn">портянку</a> на vbs, которая к тому же не заработала на моей ОС(так как AD там нет и быть не может). <br />Как оказалось, всё гораздо проще можно реализовать воспользовавшись <strong>.NET</strong>. Под данную реализацию потребуется версия 3.5(и выше - требуется наличие System.DirectoryServices.AccountManagement.PrincipalContext).</p><p>Для тех кто не сталкивался с OpenVPN в кратце поясню. При авторизации пользователя(помимо сертификатов и пр.) можно запросить у пользователя логин-пароль и проверить его в системных учётках ОС. Для этого в конфиге указывается скрипт, которому при запуске в виде параметра передаётся имя файла. В файле(временный, на время авторизации) содержится всего две строки - логин и пароль. В результате работы скрипта должен вернуться код завершения 0(успешная авторизация) или 1(не удалось авторизоваться).</p><p>Протестировано на:<br /></p><ul><li><p>Windows XP Pro SP3, VS2008(.NET 3.5)</p></li><li><p>Windows 2003 Server Web Edition, VB.NET 2010 Express(.Net 4.0 - на сайте MS 2008-ую эспресс студию уже не нашел)</p></li></ul><p>Приложение консольное. В проекте нужно добавить ссылку на System.DirectoryServices.AccountManagement.<br /></p><div class="codebox"><pre><code>
Module WinAuth
    Dim logfile As System.IO.StreamWriter
    Dim pwdfile As System.IO.StreamReader
    Function Main(ByVal cmdArgs() As String) As Integer
        Dim instance As System.DirectoryServices.AccountManagement.PrincipalContext
        Dim usrName As String
        Dim usrPass As String
        Dim returnValue As Boolean
        logfile = My.Computer.FileSystem.OpenTextFileWriter(&quot;winauth.log&quot;, True, _
                                                    System.Text.Encoding.GetEncoding(1251))
        logfile.AutoFlush = True
        If cmdArgs.Count &lt;&gt; 1 Then
            Echo(&quot;Wrong parametrs.&quot;)
            Return 1
        Else
            Try
                pwdfile = My.Computer.FileSystem.OpenTextFileReader(cmdArgs(0).ToString, _
                                                    System.Text.Encoding.GetEncoding(1251))
            Catch ex As Exception
                Echo(ex.Message.ToString)
                Echo(&quot;pwdfile not found.&quot;)
            End Try

            Try
                usrName = pwdfile.ReadLine.ToString
            Catch ex As Exception
                Echo(ex.Message.ToString)
                Echo(&quot;No data in pwdfile.&quot;)
                Return 1
            End Try

            Try
                usrPass = pwdfile.ReadLine.ToString
            Catch ex As Exception
                Echo(ex.Message.ToString)
                Echo(&quot;No password in pwdfile.&quot;)
                Return 1
            End Try

        End If
        pwdfile.Close()
        instance = New System.DirectoryServices.AccountManagement.PrincipalContext( _
            System.DirectoryServices.AccountManagement.ContextType.Machine, _
            System.Environment.MachineName.ToString)
        Try
            returnValue = instance.ValidateCredentials(usrName, usrPass)
        Catch ex As Exception
            Echo(ex.Message.ToString)
            Return 1
            &#039;Error Codes list for Microsoft technologies:
            &#039;http://www.symantec.com/business/support/index?page=content&amp;id=TECH12638
            &#039;&quot;HRESULT: 0x80070533&quot; == &quot;Logon failure: account currently disabled.&quot;
        End Try

        Select Case returnValue
            Case False
                Echo(&quot;Logon failure: username or password incorrect.&quot;)
                Return 1
            Case True
                Echo(&quot;Logon is successful.&quot;)
                Return 0
            Case Else
                Echo(&quot;Unknown Error?&quot;)
                Return 1
        End Select
    End Function
    Sub Echo(ByVal text)
        Console.WriteLine(text)
        Debug.Print(text)
        logfile.WriteLine(Now() &amp; &quot;:&gt; &quot; &amp; text)
    End Sub
End Module
</code></pre></div><p>На всякий случай прокоментирую один момент:<br /></p><div class="codebox"><pre><code>        instance = New System.DirectoryServices.AccountManagement.PrincipalContext( _
            System.DirectoryServices.AccountManagement.ContextType.Machine, _
            System.Environment.MachineName.ToString)</code></pre></div><p>В качестве второго параметра доступно:<br /></p><ul><li><p>System.DirectoryServices.AccountManagement.ContextType.Machine</p></li><li><p>System.DirectoryServices.AccountManagement.ContextType.Domain</p></li><li><p>System.DirectoryServices.AccountManagement.ContextType.ApplicationDirectory</p></li></ul><p>Вторым параметром идёт сервер для авторизации. На Win2003WE сработало &quot;localhost&quot;, на WinXP по какой-то причине не прокатило - но работало по IP(127.0.0.1). Посмотрел чем богат дотнет, и поставил имя машины. Работает на обоих компьютерах.</p><p>Конечно, как минимум вывод сообщений лучше допилить под себя(или убрать совсем) - вариант выше в некоторой степени beta <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" />.</p><p>Надеюсь кому нибудь пригодится.</p><p>P.S. В найденном vbs-варианте так же проверялась принадлежность пользователя конкретной группе. В моём коде это не реализовано(так как пока такой задачи не стоит), но не думаю что в .NET с этим будут проблемы.</p>]]></description>
			<author><![CDATA[null@example.com (BeS Yara)]]></author>
			<pubDate>Wed, 11 Dec 2013 11:24:07 +0000</pubDate>
			<guid>http://forum.script-coding.com/viewtopic.php?pid=78012#p78012</guid>
		</item>
	</channel>
</rss>
