e0cbc4c215727c843eea2c6dc7fe1b6b652296d5
[kopensolaris-gnu/glibc.git] / sysdeps / unix / sysv / solaris2 / kopensolaris-gnu / privP.c
1 /* Copyright (C) 2008 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by David Bartley <dtbartle@csclub.uwaterloo.ca>, 2008.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <privP.h>
21 #include <priv.h>
22 #include <bits/libc-lock.h>
23
24 __libc_lock_define_recursive (extern, __priv_lock);
25 libc_freeres_ptr (static priv_data_t *__data);
26 static priv_set_t *__suidset = NULL;
27
28 priv_data_t * __priv_parse_info (const priv_impl_info_t *pii)
29 {
30   priv_data_t *data = malloc (sizeof (priv_data_t));
31   if (!data)
32     return NULL;
33   memset (data, 0, sizeof (*data));
34   data->pd_setsize = pii->priv_setsize * sizeof (priv_chunk_t);
35
36   /* Iterate over all priv_info_t's. Note that the first priv_info_t follows
37      the header.  */
38   priv_info_t *pi = (priv_info_t *)((char *)pii + pii->priv_headersize);
39   uint32_t left = pii->priv_globalinfosize;
40   while (left)
41     {
42       switch (pi->priv_info_type)
43         {
44         case PRIV_INFO_SETNAMES:
45         case PRIV_INFO_PRIVNAMES:
46           if ((pi->priv_info_type == PRIV_INFO_SETNAMES &&
47                 data->pd_setnames) || (pi->priv_info_type ==
48                 PRIV_INFO_PRIVNAMES && data->pd_privnames))
49             break;
50
51           /* XXX: In priv_get*byname we linearlly scan the list of strins;
52              we could speed this up by sorting the strings here.  */
53
54           priv_info_names_t *pi_names = (priv_info_names_t *)pi;
55
56           /* Allocate memory for the index.  */
57           char **name_list = malloc (sizeof (char *) * pi_names->cnt);
58           if (!name_list)
59             goto err;
60           if (pi->priv_info_type == PRIV_INFO_SETNAMES)
61             {
62               data->pd_setnames = name_list;
63               data->pd_setnames_cnt = pi_names->cnt;
64             }
65           else
66             {
67               data->pd_privnames = name_list;
68               data->pd_privnames_cnt = pi_names->cnt;
69             }
70           data->pd_privnames_cnt = pi_names->cnt;
71
72           /* Setup the index.  */
73           char *names_ptr = pi_names->names;
74           for (int i = 0; i < pi_names->cnt; i++)
75             {
76               name_list[i] = names_ptr;
77               names_ptr += strlen (names_ptr) + 1;
78             }
79
80           break;
81
82         case PRIV_INFO_BASICPRIVS:
83           if (data->pd_basicprivs)
84             break;
85
86           if (pi->priv_info_size != data->pd_setsize)
87             break;
88           data->pd_basicprivs = ((priv_info_set_t *)pi)->set;
89
90           break;
91         }
92
93       left -= pi->priv_info_size;
94       pi = (priv_info_t *)((char *)pi + pi->priv_info_size);
95     }
96
97   return data;
98
99 err:
100
101   free (data->pd_setnames);
102   free (data->pd_privnames);
103   free (data);
104
105   return NULL;
106 }
107
108
109 void __priv_free_info (priv_data_t *data)
110 {
111   free (data->pd_setnames);
112   free (data->pd_privnames);
113   free (data);
114 }
115
116
117 const priv_data_t * __priv_parse_data_cached (void)
118 {
119   if (__data)
120     return __data;
121
122   __libc_lock_lock_recursive (__priv_lock);
123   __data = __priv_parse_info (getprivimplinfo ());
124   __libc_lock_unlock_recursive (__priv_lock);
125
126   return __data;
127 }
128
129
130 #if 0
131 int __init_suid_priv (int flags, ...)
132 {
133   // TODO
134 }
135 #endif
136
137
138 int __priv_bracket (priv_op_t op)
139 {
140   if (op != PRIV_ON && op != PRIV_OFF)
141     {
142       __set_errno (EINVAL);
143       return -1;
144     }
145
146   /* We can only toggle privileges if __init_suid_priv was called.  */
147   if (__suidset)
148     return setppriv (op, PRIV_EFFECTIVE, __suidset);
149   else
150     return 0;
151 }
152
153
154 void __priv_relinquish (void)
155 {
156   if (__suidset)
157     {
158       setppriv (PRIV_OFF, PRIV_PERMITTED, __suidset);
159       priv_freeset (__suidset);
160       __suidset = NULL;
161     }
162 }