Tizen 2.1 base
[framework/security/security-server.git] / src / security-srv / include / SLP_security-server_PG.h
1 /**
2  *
3  * @ingroup   SLP_PG
4  * @defgroup  Security_Server_PG Security Server
5 @{
6
7 <h1 class="pg">Introduction</h1>
8 <p>In Linux system, access control is enforced in the kernel space objects such as file, socket, directory, and device which are all described as files. In SLP, many objects are defined in user space which cannot be described as file, for example, make a phone call, send a SMS message, connect to the Internet, and modify SIM password. Some of the objects in user space are very sensitive to the platform and the phone business as well as user's property. Therefore the user space objects needed to be protected.</p>
9 <p>To protect such user space objects, there must be a kind of credential to decide access result, and the credential must be trusted. Since process has privileges and the objects only has label, so some trusted entity should check the process has right privilege to access objects, and the security hooks to check this privilege should be located in the each middleware service daemons which provide the objects to the applications.</p>
10 <p>Security Server uses group IDs of Linux system that are assigned to each process. In detail, if a process requests to get some user-space service to a middleware daemon, the middleware daemon requests to check privilege of some process, then the security server checks given gid is assigned to the process or not. If yes, then return yes, if no, then return no.</p>
11 <p>If an application and middleware daemon uses Linux standard IPC such as Unix domain socket, there is no need to introduce 3rd party process to check gid that the process has. But some of service uses non Linux standard IPC such as telephony - using dbus - which the peer's credential is not propagated to the other peer. As a result to meet all the system's environment, we introduce Security Server.</p>
12 <p>
13 Security Server uses a random token named "cookie" to identify a process, the cookie needed not to be abled to guess easily, so it's quite long (currently 20 bytes), and only kept by Security Server process memory</p>
14
15 <h1 class="pg">Security Server Architecture</h1>
16 @image html SLP_Security-Server_PG_image001.png
17 <p>Above fiture explains software architecture of Security Server. It is client-server structure, and communicates by IPC. The IPC must be point-2-point mechanism such as UNIX domain socket, not server related IPC such as dbus, because it's not easy to guarantee the other peer's security.</p>
18 <p>Application or middleware process can call Security Server API to assign a new cookie or checking privilege of the given cookie. In this case, client library authenticates IPC peer and check the peer is Security Server process. In the same sense, Security Server authenticates client also.</p>
19 <p>Application requests cookie to Security Server before requesting the service to the middleware daemon. Security Server authenticates the client, generates a random cookie, stores the cookie into local memory, and responds to the client with the cookie value. Client loads the cookie in the request message and sends to the middleware server, then the receiver middleware daemon check the privilege of the given cookie by calling Security Server API. Security Server compares received cookie value with stored cookie, checks and responds to the middleware daemon. Finally middleware daemon knows the client's privilege and it decides continue or block the request.</p>
20
21 <h2>Sub components</h2>
22
23 <h3>Client library</h3>
24 @image html SLP_Security-Server_PG_image002.png
25 <p>Client library is linked to application or middleware daemon. Therefore it belongs to the caller process, so uid, pid, and groups are also same. If the application calls cookie request API, the client compose cookie request message and sends to the Security Server and wait for the response. After receiving the response, first checks the response is from Security Server, and if it's true, it stores cookie into cookie container.</p>
26 <p>Middleware daemon also links same client library, but by the difference of the calling APIs, the functions are different. Middleware daemon first receives cookie value loaded in service request from the client, and then the middleware calls Security Server API to check the cookie has the privilege to the service and waits for the response. After receiving the response, it authenticates the response is really from Security Server, and continue service by the result of the API.</p>
27
28 <h3>Security Server Daemon</h3>
29 @image html SLP_Security-Server_PG_image003.png
30 <p>Security Server daemon is a Unix domain socket server, but it only has single thread and single process to get rid of race condition for the proc file system and cookie list to be shared. It’s easy to manage, more secure and the Security Server itself doesn't need to maintain a session for a long time.</p>
31 <p>When request API is received from the client, Security Server first parses, and authenticates the message, and creates cookie or checks privilege. Cookie is a 20 bytes random string too hard to be guessed. So it's hard to be spoofed.</p>
32 <p>Cookie generator generates a cookie based on proc file system information of the client process with group IDs the client belongs to, and privilege checker searches received cookie value with stored cookie list and checks the privilege.</p>
33 <p>Cookie list is a linked list implemented in memory and it stores and manages generated cookie.</p>
34
35 <h1 class="pg">Dependency</h1>
36 <p>The Security Server has high dependency on Linux kernel, precisely the proc file system. Since Security Server refers to proc file system with processes group ID, so the kernel must support group ID representation on the proc file system.</p>
37 <p>In kernel version 2.6, there is a file in proc file system "/proc/[pid]/status" which describes various information about the process as text, it has a line named "Groups:" and it lists the group IDs that the process is belonged to. But there is a drawback in this file, it only shows at most 32 group IDs, if number of groups of the process is bigger than 32, it ignores them.</p>
38 <p>To enable to show all the groups you have to patch the kernel source code to show more groups than 32, but there is another drawback. All files in the proc file system has size limit to 4k bytes because the file buffer size is 4k bytes, so it's not possible to show all possible groups of the process (64k), but currently number of all groups in the LiMo platform is much lower than the size, so it's not a big problem. But near future we need to apply this patch into kernel mainline source code by any form.</p>
39
40 <h1 class="pg">Scenarios</h1>
41 @image html SLP_Security-Server_PG_image004.png
42 <p>Security Server process view is described in figure above. It's explained in above, so it's not necessary to explain again. But one possible question may arise, that why do we need Security Server, that the service daemon can authenticates application process by the IPC, and the daemon can check proc file system by itself, so it seems that we may not need to have Security Server at all<p>
43 @image html SLP_Security-Server_PG_image005.png
44 <p>But there is exceptional process view described in figure above. If the middleware's IPC mechanism is dbus, then the daemon cannot guarantee the identity of the requesting application. In this case, there is no possible way to check and authenticate application from the middleware daemon directly. We need a trusted 3rd party to guarantee such identity and privilege, therefore Security Server is required.</p>
45 <p>As described above, the cookie value is the key of the security of Security Server. The cookie value must not to be exposed into the platform, the cookie value must be stored securely that only Security Server and the application process knows the value. Even the middleware daemon should not cache the cookie for the security reason</p>
46
47 <h1 class="pg">APIs</h1>
48
49 <h3 class="pg">security_server_get_gid</h3>
50 <table>
51         <tr>
52                 <td>
53                         API Name:
54                 </td>
55                 <td>
56                         gid_t security_server_get_gid(const char *object)
57                 </td>
58         </tr>
59         <tr>
60                 <td>
61                         Input Parameter:
62                 </td>
63                 <td>
64                         object name as Null terminated string
65                 </td>
66         </tr>
67         <tr>
68                 <td>
69                         Output Parameter:
70                 </td>
71                 <td>
72                         N/A
73                 </td>
74         </tr>
75         <tr>
76                 <td>
77                         Return value:
78                 </td>
79                 <td>
80                         On success, returns the integer gid of requested object.<br>
81                         On fail, returns negative integer
82                 </td>
83         </tr>
84 </table>
85 This API returns the gid from given object name. This API is only allowed to be called from middleware service daemon which is running under root privilege
86
87 <h3 class="pg">security_server_get_object_name</h3>
88 <table>
89         <tr>
90                 <td>
91                         API Name:
92                 </td>
93                 <td>
94                         int security_server_get_object_name(gid_t gid, char *object, size_t max_object_size)
95                 </td>
96         </tr>
97         <tr>
98                 <td>
99                         Input Parameter:
100                 </td>
101                 <td>
102                         gid, max_object_size
103                 </td>
104         </tr>
105         <tr>
106                 <td>
107                         Output Parameter:
108                 </td>
109                 <td>
110                         object as null terminated string
111                 </td>
112         </tr>
113         <tr>
114                 <td>
115                         Return value:
116                 </td>
117                 <td>
118                         On success, returns 0<br>
119                         On fail, returns negative integer
120                 </td>
121         </tr>
122 </table>
123 This API is opposite with security_server_get_gid(). It converts given gid to object name which buffer size is max_object_size. If object name is bigger then max_object_size then it returns SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMAL error.
124
125 <h3 class="pg">security_server_request_cookie</h3>
126 <table>
127         <tr>
128                 <td>
129                         API Name:
130                 </td>
131                 <td>
132                         gid_t security_server_request_cookie(char *cookie, size_t max_cookie)
133                 </td>
134         </tr>
135         <tr>
136                 <td>
137                         Input Parameter:
138                 </td>
139                 <td>
140                         max_cookie
141                 </td>
142         </tr>
143         <tr>
144                 <td>
145                         Output Parameter:
146                 </td>
147                 <td>
148                         cookie
149                 </td>
150         </tr>
151         <tr>
152                 <td>
153                         Return value:
154                 </td>
155                 <td>
156                         On success, returns 0<br>
157                         On fail, returns negative integer
158                 </td>
159         </tr>
160 </table>
161 This API requests a cookie to Security Server. max_cookie is the size of buffer cookie to be filled with cookie value, if max_cookie smaller then cookie size, then this API returns SECURITY_SERVER_API_ERROR_BUFFER_TOO_SMAL error.
162
163 <h3 class="pg">security_server_get_cookie_size</h3>
164 <table>
165         <tr>
166                 <td>
167                         API Name:
168                 </td>
169                 <td>
170                         int security_server_get_cookie_size(void)
171                 </td>
172         </tr>
173         <tr>
174                 <td>
175                         Input Parameter:
176                 </td>
177                 <td>
178                         N/A
179                 </td>
180         </tr>
181         <tr>
182                 <td>
183                         Output Parameter:
184                 </td>
185                 <td>
186                         N/A
187                 </td>
188         </tr>
189         <tr>
190                 <td>
191                         Return value:
192                 </td>
193                 <td>
194                         size of cookie value
195                 </td>
196         </tr>
197 </table>
198 This API simply returns the size of cookie.
199
200 <h3 class="pg">security_server_check_privilege</h3>
201 <table>
202         <tr>
203                 <td>
204                         API Name:
205                 </td>
206                 <td>
207                         int security_server_check_privilege(const char *cookie, gid_t privilege)
208                 </td>
209         </tr>
210         <tr>
211                 <td>
212                         Input Parameter:
213                 </td>
214                 <td>
215                         cookie, privilege
216                 </td>
217         </tr>
218         <tr>
219                 <td>
220                         Output Parameter:
221                 </td>
222                 <td>
223                         N/A
224                 </td>
225         </tr>
226         <tr>
227                 <td>
228                         Return value:
229                 </td>
230                 <td>
231                         On success, returns 0<br>
232                         On fail, returns negative integer
233                 </td>
234         </tr>
235 </table>
236 This API checks the cookie value has privilege for given gid. This API should be called by middleware server only after application embed cookie into the request message and sent to the middleware server. The middleware server should aware with the privilege parameter because it knows the object which the client application tries to access.
237
238
239 <h1 class="pg">Implementation Guide</h1>
240
241 <h2>Middleware server side</h2>
242 <p>
243 In middleware, implementation is focused on checking privilege of the requested client application. To call security_server_check_privilege() API, you have to get the gid value first, and this can be achieved by calling security_server_get_gid() API. The pre-condition of this scenario is that the middleware server knows the name of the object. Once you get the gid values, you can cache them for better performance. </p>
244 <p>
245 Once a client application requests to access the middleware’s object, the client should embed cookie into the request message. If not, the security is not guaranteed. After getting request and embedded cookie, the middleware server call security_server_check_privilege() API to check the client is allowed to access the object, the security server will respond the result. Finally the server need to decide continue the service or not.</p>
246
247 @code
248 static gid_t g_gid;
249
250 int get_gid()
251 {
252         int ret;
253         // Get gid of telephony call - example object
254         ret = security_server_get_gid("telephony_call");
255         if(ret < 0)
256         {
257                 return -1;
258         }
259         g_gid = ret;
260         return 0;
261 }
262
263 int main(int argc, char * argv[])
264 {
265         char *cookie = NULL;
266         int ret, cookie_size;
267
268
269         ...
270
271
272                 // Initially get gid about the object which is interested in
273                 if(get_gid() < 0)
274                         exit(-1);
275
276         // get cookie size and malloc it if you want
277         cookie_size = security_server_get_cookie_size();
278         cookie = malloc(cookie_size);
279
280         ...
281
282         // If a request has been received
283         // First parse the request and get the cookie value
284         // Let's assume that the buffer cookie is filled with received cookie value
285         ret = security_server_check_privilege(cookie, cookie_size);
286         if(ret == SECURITY_SERVER_API_ERROR_ACCESS_DENIED)
287         {
288                 // Access denied
289                 // Send error message to client application
290         }
291         else if( ret != SECURITY_SERVER_SUCCESS)
292         {
293                 // Error occurred
294                 // Check error condition 
295         }
296         else
297         {
298                 // Access granted
299                 // Continue service
300                 ...
301         }
302
303
304         ...
305
306
307         free(cookie);
308         ...
309 }
310 @endcode
311
312 <h2>Client application side</h2>
313 <p>
314 In client application, what you need is just request a cookie and embed it into request message</p>
315
316 @code
317 int some_platform_api()
318 {
319         char *cookie = NULL;
320         int cookie_size, ret;
321
322         ...
323
324
325         // malloc the cookie
326         cookie_size = security_server_get_cookie_size();
327         cookie = malloc(cookie_size);
328
329         ...
330
331
332                 // Request cookie from the security server
333                 ret = security_server_request_cookie(cookie, cookie_size);
334         if(ret < 0)
335         {
336                 // Some error occurred
337                 return -1;
338         }
339
340         // embed cookie into the message and send to the server
341
342         ...
343         free(cookie);
344 }
345 @endcode
346
347 */
348 /**
349 *@}
350 */