Никто не любит лишний раз вводить пароли. В мире веб-приложений протоколы для SSO (Single Sign-On) широко распространены и легко реализуемы благодаря встроенной в браузер возможности хранить cookie. Со стороны безопасности это не лучшее решение. Ряд популярных приложений, к примеру консольный клиент PostgreSQL (psql), предоставляют такую возможность для локальных подключений через сокеты UNIX. В этой статье мы рассмотрим, как это сделать с помощью опции SO_PEERCRED.

В качестве примера мы напишем сервер, который просто хранит какое-то число, при этом пользователи из группы wheel могут его изменять, а все остальные — только получать значение. Писать будем на Python, но все сказанное применимо к любому языку.

В этой статье речь идет о Linux, если не указано обратное.

 

Абстрактные сокеты Linux

Для взаимодействия с сервером мы будем использовать вариант UNIX domain sockets — abstract namespace sockets. В отличие от сетевых сокетов, в случае с локальными сокетами UNIX ядро знает, какой процесс подключается к сокету, и знает все о пользователе (создателе) процесса, что и позволяет переиспользовать системную аутентификацию.

В классической реализации сокеты UNIX представляют собой файлы. Это позволяет применить к ним права доступа и запретить пользователям или группам подключаться к ним, но более сложную модель привилегий на этом не построить.

Основной недостаток классической реализации — опция SO_REUSEADDR для них не работает. Файл сокета должен быть создан процессом, который на нем слушает. Если процесс упал, а файл сокета остался, то новому процессу сначала нужно его удалить. Правильно написанный сервер должен использовать lock-файлы, чтобы предотвратить случайный запуск нескольких экземпляров процесса и обеспечить безопасное удаление старого файла.

Для решения этой проблемы в Linux существуют так называемые abstract namespace sockets. По своей сути они идентичны традиционным сокетам UNIX, но не являются файлами и автоматически исчезают с завершением процесса, который их создал. К ним также неприменимы обычные права доступа, и авторизация остается на совести приложения — но мы ведь к этому и стремимся.

Чтобы создать абстрактный сокет, нужно добавить в начало его «пути к файлу» нулевой байт. В остальном все так же, как с обычными.

 

Пишем сервер

Для начала мы напишем основу для сервера, пока без авторизации. Чтобы не писать разбор сообщений, мы сделаем всего две команды без аргументов: read (вернуть значение счетчика) и inc (увеличить счетчик на единицу).

Сокет мы назовем counter-server. Соответственно, путь его будет '\0counter-server'.

#!/usr/bin/env python3

import os
import socket

SOCK_FILE = '\0counter-server'

## Счетчик
counter = 0

## Создаем сокет
sock = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM)
sock.bind(SOCK_FILE)
sock.listen()

while True:
    conn, _ = sock.accept()

    command = conn.recv(1024).decode().strip()

    if command == 'inc':
        print("Received an increment request")
        counter += 1
        response = "Success"
    elif command == 'read':
        print("Received a read request")
        response = "Counter value: {0}".format(counter)
    else:
    response = "Invalid command"

    conn.send(response.encode())
    conn.send(b'\n')
    conn.close()

Попробуем запустить его:

$ sudo ./counter-server.py 
Counter server started

Перейдем в другую консоль и попробуем подключиться с помощью socat. В случае с обычным stream-сокетом протокол был бы UNIX-CONNECT, но поскольку наш — «необычный», нужен ABSTRACT-CONNECT.

$ socat - ABSTRACT-CONNECT:counter-server 
inc
Success

$ socat - ABSTRACT-CONNECT:counter-server 
read
Counter value: 1

Продолжение доступно только участникам

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    4 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии