[.Net 4, cross-process singleton] Покритикуйте код
От: Sinix  
Дата: 02.10.10 14:02
Оценка:
Вчерновую накидал cross-process singleton на named pipes, плиз потыкайте носом

Ясен пень, что до юзабельного состояния пилить и пилить: вынести в отдельный класс, добавить разные имена для разных сессий, не забыть про обработку ошибок, запуск в фоновом потоке, прерывание работы и т.д. и т.п.

Меня сейчас интересуют в первую очередь упущенные нюансы/неверно указанные параметры/безопасность. Например, я почти уверен, что в коде дырка: не блокируются удалённые соединения. В понедельник буду на работе, проверю.

  код
using System;
using System.IO;
using System.IO.Pipes;
using System.Security.AccessControl;
using System.Security.Principal;

namespace ProcessSingleInstance
{
  class Program
  {
    static void Main(string[] args)
    {
      string[] data = new[] { "a", "aaaaa", "qweqeqweqeqweqwert" };

      NamedPipeServerStream server = null;
      try
      {
        server = CreateServerStream();
      }
      catch (UnauthorizedAccessException)
      {
      }

      if (server != null)
      {
        RunServer(server);
      }
      else
      {
        RunClient(data);
      }
    }

    // критиковать здесь.
    // Сервер должен _только_ читать данные;
    // не должен позволять соединения вне текущей сессии, в т.ч. удалённые
    private static NamedPipeServerStream CreateServerStream()
    {
      PipeSecurity security = new PipeSecurity();

      security.AddAccessRule(
        new PipeAccessRule(
          WindowsIdentity.GetCurrent().User,
          PipeAccessRights.Synchronize
          | PipeAccessRights.ReadAttributes // DONTTOUCH: Required. I don't know why.
          | PipeAccessRights.Write,
          AccessControlType.Allow));

      NamedPipeServerStream server = new NamedPipeServerStream(
        "server",
         PipeDirection.In, 1,
         PipeTransmissionMode.Message, PipeOptions.WriteThrough, // Не уверен. Может, всё-таки использовать буфер?
         4096, 4096,
         security, HandleInheritability.None);

      return server;
    }

    // и здесь
    private static NamedPipeClientStream CreateClientStream()
    {
      NamedPipeClientStream client = new NamedPipeClientStream(
        ".", "server",
        PipeDirection.Out, PipeOptions.WriteThrough, TokenImpersonationLevel.None, HandleInheritability.None);
      
      return client;
    }

    private static void RunServer(NamedPipeServerStream server)
    {
      while (true)
      {
        Console.WriteLine("Wait...");
        BinaryReader r = new BinaryReader(server);
        server.WaitForConnection();

        try
        {
          int count = r.ReadInt32();
          for (int i = 0; i < count; i++)
          {
            Console.WriteLine(r.ReadString());
          }
        }
        catch (IOException)
        { }

        server.Disconnect();
      }
    }
    private static void RunClient(string[] data)
    {
      using (NamedPipeClientStream client = CreateClientStream())
      {
        client.Connect();
        using (BinaryWriter w = new BinaryWriter(client))
        {
          try
          {
            w.Write(data.Length);
            foreach (var item in data)
            {
              w.Write(item);
            }

            client.WaitForPipeDrain();
          }
          catch (IOException)
          { }
        }
      }
    }
  }
}
Re: [.Net 4, cross-process singleton] Покритикуйте код
От: hardcase Пират http://nemerle.org
Дата: 02.10.10 21:18
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Вчерновую накидал cross-process singleton на named pipes, плиз потыкайте носом


А это на COM+ нельзя разве решить?
/* иЗвиНите зА неРовнЫй поЧерК */
Re: [.Net 4, cross-process singleton] Покритикуйте код
От: Jolly Roger  
Дата: 03.10.10 02:25
Оценка: 24 (1)
Здравствуйте, Sinix, Вы писали:

S>// не должен позволять соединения вне текущей сессии, в т.ч. удалённые


В другой сессии может быть запущен процесс от имени юзера текущей сессии. И даже на другой машине, если это доменная учётка.

S>PipeTransmissionMode.Message, PipeOptions.WriteThrough, // Не уверен. Может, всё-таки использовать буфер?


Ага Through применим только для byte-mode, и только если клиент и сервер находятся на разных машинах. А в Вашем случае этот флаг будет просто проигнорирован как не имеющий смысла.
"Нормальные герои всегда идут в обход!"
Re[2]: [.Net 4, cross-process singleton] Покритикуйте код
От: Sinix  
Дата: 03.10.10 03:16
Оценка:
Здравствуйте, hardcase, Вы писали:

H>А это на COM+ нельзя разве решить?

Оверкилл. Возни с ним много (регистрация та же) а преимуществ 0. Да ещё использоваться будет в софте с "установкой копированием".
Re[2]: [.Net 4, cross-process singleton] Покритикуйте код
От: Sinix  
Дата: 03.10.10 03:24
Оценка:
Здравствуйте, Jolly Roger, Вы писали:


JR>В другой сессии может быть запущен процесс от имени юзера текущей сессии. И даже на другой машине, если это доменная учётка.


Спс. Я быстренько покопался во внутренностях: кажется, что фильтрацию по IP/данным к NamedPipeServerStream клиента не прикрутить. Либо переходить на WCF (а там это возможно будет?) либо попробовать что-то ещё (что? в голову ничего разумного не приходит), либо забить и вернуться к реализации на глюкодырявом ремотинге

JR>Ага Through применим только для byte-mode, и только если клиент и сервер находятся на разных машинах. А в Вашем случае этот флаг будет просто проигнорирован как не имеющий смысла.

От оно чё...
Re[3]: [.Net 4, cross-process singleton] Покритикуйте код
От: Jolly Roger  
Дата: 03.10.10 03:37
Оценка: 8 (1)
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, hardcase, Вы писали:


H>>А это на COM+ нельзя разве решить?

S>Оверкилл. Возни с ним много (регистрация та же) а преимуществ 0. Да ещё использоваться будет в софте с "установкой копированием".

Вообще-то в случае COM без регистрации вполне можно обойтись, вот здесь
Автор: Jolly Roger
Дата: 07.09.10
я описывал, как. На шарпе, думаю, это тоже реализуемо. Для захвата приоритета можно использовать стандартную схему с мьютексом, а интерфейс сервера раздавать через Running Object Table (ROT). На пайпах требование по поводу чужих сессий реализовать, по-моему, намного сложнее.
"Нормальные герои всегда идут в обход!"
Re[3]: [.Net 4, cross-process singleton] Покритикуйте код
От: Jolly Roger  
Дата: 03.10.10 03:59
Оценка:
Здравствуйте, Sinix, Вы писали:

S> Либо переходить на WCF (а там это возможно будет?)


На WCF пайпы как раз работают только локально (если только в 4.0 не поменяли), но вот фильтровать по сессиям вряд-ли удастся просто, если вообще.

S> вернуться к реализации на глюкодырявом ремотинге


Но-но Когда этот "ремонтник" появился, создатели его позиционировали как супер-пупер киллера всех остальных технологий удалённого взаимодействия. Ну прям как WCF сейчас
"Нормальные герои всегда идут в обход!"
Re[3]: [.Net 4, cross-process singleton] Покритикуйте код
От: Jolly Roger  
Дата: 03.10.10 04:07
Оценка: +1 :)
Здравствуйте, Sinix, Вы писали:

Offtop и баян, но забавно:)
"Нормальные герои всегда идут в обход!"
Re[4]: [.Net 4, cross-process singleton] Покритикуйте код
От: Sinix  
Дата: 03.10.10 04:10
Оценка: 14 (1)
Здравствуйте, Jolly Roger, Вы писали:

JR>На WCF пайпы как раз работают только локально (если только в 4.0 не поменяли), но вот фильтровать по сессиям вряд-ли удастся просто, если вообще.

[нецензурно-унылое выражение разочарования в несовершенстве мира].

Наткнулся на серию постов — с WCF граблей не меньше. Но удалённые соединения допускает.
http://blogs.charteris.com/blogs/chrisdi/archive/tags/WCF/default.aspx
Что ж делать-то?

S>> вернуться к реализации на глюкодырявом ремотинге

JR>Но-но
Дык не спорю. Когда вляпался, WTF было девизом дня.
http://www.rsdn.ru/forum/dotnet/3389286.flat.aspx
Автор: Sinix
Дата: 14.05.09

http://www.rsdn.ru/forum/dotnet/3390879.flat.aspx
Автор: Sinix
Дата: 15.05.09


P.S. WPF, WCF, WTF...
Re[5]: [.Net 4, cross-process singleton] Покритикуйте код
От: Jolly Roger  
Дата: 03.10.10 04:27
Оценка: 1 (1)
Здравствуйте, Sinix, Вы писали:

S>Что ж делать-то?


Ну дык каждый ищет там, где ему светлее Я-бы мьютекс и COM использовал — для работы без регистрации код один раз пишется, а ROT позволяет исключить подключения из чужих сессий, а удалённым он вообще недоступен.
"Нормальные герои всегда идут в обход!"
Re[6]: [.Net 4, cross-process singleton] Покритикуйте код
От: Sinix  
Дата: 03.10.10 04:36
Оценка: +1
Здравствуйте, Jolly Roger, Вы писали:

JR>Ну дык каждый ищет там, где ему светлее


C COMом знаком только заочно, связываться сейчас ради решения "один раз сделал — всю жизнь мучаешься" не рискну. Ну, и смысл откатываться с устаревшего, но работающего remoting'а на ещё более легаси, но, возможно, работающий ещё лучше COM+ —

Пойду копаться в the new shining code, шоб его...

Спасибо!
Re[5]: [.Net 4, cross-process singleton] Покритикуйте код
От: Jolly Roger  
Дата: 03.10.10 11:56
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Наткнулся на серию постов — с WCF граблей не меньше. Но удалённые соединения допускает.

S>http://blogs.charteris.com/blogs/chrisdi/archive/tags/WCF/default.aspx

Спасибо, интересная ссылка
"Нормальные герои всегда идут в обход!"
Re: [.Net 4, cross-process singleton] Покритикуйте код
От: Sinix  
Дата: 05.10.10 01:57
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Меня сейчас интересуют в первую очередь упущенные нюансы/неверно указанные параметры/безопасность. Например, я почти уверен, что в коде дырка: не блокируются удалённые соединения. В понедельник буду на работе, проверю.


Проверил. Дырка. Гугль молчит
Re[2]: [.Net 4, cross-process singleton] Покритикуйте код
От: Jolly Roger  
Дата: 05.10.10 02:29
Оценка: 24 (1) +1
Здравствуйте, Sinix, Вы писали:

S>>Например, я почти уверен, что в коде дырка: не блокируются удалённые соединения. В понедельник буду на работе, проверю.


S>Проверил. Дырка. Гугль молчит


Попробуйте в PipeSecurity добавить явный запрет для Network users.

S>с WCF граблей не меньше. Но удалённые соединения допускает.


Пайпы-то работают. Я имел в виду, что это искусственно зарезано в NamedPipeBinding
"Нормальные герои всегда идут в обход!"
Re[2]: [.Net 4, cross-process singleton] Покритикуйте код
От: Jolly Roger  
Дата: 05.10.10 02:53
Оценка:
Здравствуйте, Sinix, Вы писали:

По поводу локальных чужих сессий — в принципе, можно попробовать имперсонировать клиента, вытащить из маркера его SessionId (GetTokenInformation + TokenSessionId) и сравнить с текущей сессией.
"Нормальные герои всегда идут в обход!"
Re[3]: [.Net 4, cross-process singleton] Покритикуйте код
От: Sinix  
Дата: 05.10.10 03:11
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>Попробуйте в PipeSecurity добавить явный запрет для Network users.

Шикарно

Аж стыдно, что не додумался до такого простого решения
Re[3]: [.Net 4, cross-process singleton] Покритикуйте код
От: Sinix  
Дата: 05.10.10 03:36
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

JR>По поводу локальных чужих сессий — в принципе, можно попробовать имперсонировать клиента, вытащить из маркера его SessionId (GetTokenInformation + TokenSessionId) и сравнить с текущей сессией.

1) Да не, это уже оверкилл будет. И так хватит.
2) По наводке:
http://msdn.microsoft.com/en-us/library/aa379626.aspx

TokenSessionId
...
In a non-Terminal Services environment, the session identifier is zero.


Огромное спасибо!
Re[3]: [.Net 4, cross-process singleton] Покритикуйте код
От: Sinix  
Дата: 05.10.10 03:40
Оценка:
Здравствуйте, Jolly Roger, Вы писали:

UPD. Вроде бы, нужно использовать AuthenticationId из TOKEN_STATISTICS.
Re[4]: [.Net 4, cross-process singleton] Покритикуйте код
От: Jolly Roger  
Дата: 05.10.10 05:22
Оценка:
Здравствуйте, Sinix, Вы писали:

S>UPD. Вроде бы, нужно использовать AuthenticationId из TOKEN_STATISTICS.


Да нет, вероятно. AuthenticationId — это идентификатор Logon Session, это не то, его, к примеру, можно задать, используя для логона LsaLogonUser.

S>In a non-Terminal Services environment, the session identifier is zero


Ну да, если у Вас нет Terminal Services environment, то и пользовательская сессия одна-единственная => вопрос о сессиях снимается автоматически.

S>Аж стыдно, что не додумался до такого простого решения


Да ладно, мне оно тоже не сразу в голову пришло Мало иметь информацию в мозгах, нужно ещё чтобы она в нужный момент всплыла на поверхность из всего прочего хлама
"Нормальные герои всегда идут в обход!"
Re[5]: [.Net 4, cross-process singleton] Покритикуйте код
От: Sinix  
Дата: 05.10.10 05:54
Оценка:
Здравствуйте, Jolly Roger, Вы писали:


JR>Да нет, вероятно. AuthenticationId — это идентификатор Logon Session, это не то, его, к примеру, можно задать, используя для логона LsaLogonUser.


Увы да, нужен именно logon session sid. Если его добыть — даём права только сессии — вуаля Сейчас осталась единственная дырка: локально заходим одновременно под двумя пользователями, под первым запускаем сервер, под вторым (от имени первого) — клиента.

Попробую вытащить ч/з WMI и забью. Тем более что, как я понимаю, в WCF будет абсолютно та же уязвимость.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.