-
Notifications
You must be signed in to change notification settings - Fork 1
/
jan_lecture7
180 lines (95 loc) · 10.6 KB
/
jan_lecture7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
Ян. Лекция 7.
Пользовательские права.
Что хотим? Разделение возможностей при работе с ресурсами. Проверять что к данному ресурсу данный пользователь может обратиться.
Модели доступа:
Дискретная - таблица объект-субъект, и в ячейке +-R +-W +-E.
Ролевая - есть три вида документов: секретные, сов. секретные и особой важности.
И у пользователя есть возможность работать с одним из типов и всё что он генерит - становится секретным.
Есть множество меток и у объекта и у субъекта, и субъект может обращаться к объекту если одно множество(у субьекта) является подмножеством другого. то бишь секретное вложено в сов. секретно и т.д.
Идея - нельзя опустить уровень секретности (из секретного сделать несекретный)
-- есть ещё другие решения, это два самых модных.
Вторая половина проблема - как реализовать "стать юзером".
В виндовом апи - говорим "хочу стать пользователем с таким логином и паролем"
login(username, pass);
Теперь ядро должно отображать юзернеймы в субъекты, заниматься проверкой паролей, а если хотим логиниться не по паролю, а по отпечатку
пальца, то всё надо переписывать.
Можно в ProcInfo хранить
inode = {
...
nid::int - владелец файла
nid ==0 - root, все проверки игнорируются
!=0 - смотрит в таблицу и пытается понять, что можно
объекты - inode, субъекты - процессы в этом случае
mode - четыре тройки бит, например 1 7 5 5
три последних - для пользователя, для группы, для всех остальных. а в тройке - RWE.
ProcInfo = {
nid = owner:Int
gid(group id) : Int - основная группа объекта
gid_list:: [Int] - все группы, которым принадлежит объект
mode : Int
}
При проверке:
nid!=0
process.uid ?= i.nid
если нет - проверяем, совпадают ли группы
Должны быть права не только на "разрешить что-то", но и на "запретить что-то"
Для просто файлов RWE понятно что значит.
Для директорий:
Read - можно читать имена
Execute - можно читать номера inode
Write - можно что-то менять
Если сделать ls в директории, помеченной только для чтения, то он вернёт нам имена файлов, но ничего про них не скажет.
Мораль - между директорией ф файлами в ней взимодействие нетриаиальное.
Вернёмся к дериктори которой можно удалть.
Первый бит первого флага - sticky bit - если он установлен в единицу, то это значит, что файл может удалить только пользователь.
След. бит - setgid - все объекты, которые созд в этой директории наследуют gid этой директории. - мало кто знает, но очень полезная штука,
почитать ман
setuid - когда будешь исполнять, установи эффективный gid и uid в мой.
странная штука, лучше почитать маны.
Системные вызовы
setuid(uid) - если текущий uid 0, то можно поставить любой, а если не 0 - то можно поставить только тот, который уже есть.
То бишь можно только понижать привилегии и можно логиниться в любого товарища.
Как перелогиниваться?
У нас есть файловый дескриптор, который может выполнять команды более привилегированного уровня и мы у него через сокет просим поменять нам права.
Для того чтобы реализовать системные вызовы на уровне программ, делают два uid и два gid - реальный и эффективный.
Реальный - uid программы, которая сейчас работает, а эффективный - с какими правами мы сейчас работаем(кем притворяемся).
Реальный не влияет ни на что, кроме setuid, а эффективный - на всё остальное.
Что делает sudo - запускается sudo c эффективным и рутовым - и она проверяет, правда ли, что наш реальный юзер может запустить файл,
нужно ли спросить пароль и прочая.
Реальный uid нужен для того, чтобы например сказать sudo, что определённый пользователь не может ничего.
execute bit - можно сделать exec на этот файл. Если setuid в единице - то при вызове exec, файлу поставится uid юзера процесса, который файл запускает.
Эффективный - используется для проверки всех прав, а реальный - кто пользователь на самом деле.
su root - спрашивает паролль от рута.
sudo su - спрашивает пароль текущего пользователя, а потом запускает shell под рутом.
setuid(uid) если рут и ставим нерутовый - сбрасываются оба.
нерутовый и ставим в какой-то - сбрасывается только эффективный.
Если хотим поменять права - нужно пользоваться setresuid( , , );
Как объекты - могут быть
айноды(создание файловых дескрипторов),
могут быть настройки самого процесса(resuid и прочее - их тоже можно менять),
возможность послать сигнал kill и другие сигналы: чтобы процессу А можно было послать сигнал процессу B нужно, чтобы эффективный uid
A совпадал с реальным uid B. Ну а рут может слать что угодно кому захочет.
Порты TCP. Порты с номером, меньшим 1024 - может открывать только рут. Зачем - чтобы тот, кто конектится к машине знал, что с ним работает верифицированный демон, а не просто рандомный процесс, который собирает логины и пароли.
____________
PAM
Есть утилиты su, sudo , passwd(меняет пароль) и прочая - все утилиты, которые занимаются прверками прав.
/etc/passwd - написаны все имена пользователей и вся информация о этих пользователях(кроме паролей). Зачем нужен? ls лезет в этот файл, чтобы понять, по номеру пользователя его имя.
/etc/shadow - в нём написаны хэши паролей.
/etc/group - написаны все группы и все пользователи, которые в них находятся.
Заниматься парсингом этих файлов геморно - нужна либа, чтобы этим всем заниматься.
PAM - portable authentification module. Api - линкуемся, представляемся и дальше уже работаем.
Можно сделать цепочку библиотек, каждая из которых или разрешает пользователю или не разрешает.
/etc/pam
Есть сессия - такой хук, который говорит "настрой всё, что угодно". Настройка сессии происходит в самом процессе - она может делать всякие вещи, в духе поставить лимиты на количество файловых дескрипторов, менять прова и прочая. И только ради сессии стоил PAM делать библиотекой, а не демоном.
PAM - библиотека, с которой линкуются и она дёргает функции из других библиотек.
Самое клёвое - что можно настраивать лимиты процессам.
+ польза от сессий -можно не вводить пароль каждый раз, потому что в сессии пароль хранится и сам вводится.
С точки зрения PAM, сессия - просто функция в API.
getrlimit(property)
список пропертей написан в мане.
rlimits - самая модная тема, которая делается в настройках сессии.
В ProcInfo есть tti - файловый дескриптор терминала, к которому процесс в данный момент подключён.
________-
Capabilities - штуковина, которая позволяет куски прав рута дать процессу.
man capabilities
более мелкое управление правами