Merge branch 'redirect-urlauth'
[libi2ncommon] / src / userfunc.cpp
1 /*
2 The software in this package is distributed under the GNU General
3 Public License version 2 (with a special exception described below).
4
5 A copy of GNU General Public License (GPL) is included in this distribution,
6 in the file COPYING.GPL.
7
8 As a special exception, if other files instantiate templates or use macros
9 or inline functions from this file, or you compile this file and link it
10 with other works to produce a work based on this file, this file
11 does not by itself cause the resulting work to be covered
12 by the GNU General Public License.
13
14 However the source code for this file must still be made available
15 in accordance with section (3) of the GNU General Public License.
16
17 This exception does not invalidate any other reasons why a work based
18 on this file might be covered by the GNU General Public License.
19 */
20 /** @file
21  * @brief provides wrapper and tools for (system) user and group information.
22  *
23  * @copyright Intra2net AG
24  *
25  * @license commercial
26  *
27  * (c) Copyright 2007-2008 by Intra2net AG
28  */
29
30 #include "userfunc.hpp"
31
32 #include <algorithm>
33 #include <fstream>
34
35 #include <unistd.h>
36 #include <signal.h>
37 #include <errno.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
40 #include <dirent.h>
41 #include <errno.h>
42 #include <pwd.h>
43 #include <grp.h>
44
45 #include <boost/scoped_array.hpp>
46
47 namespace I2n
48 {
49
50 namespace
51 {
52
53 /*
54 ** tool functions
55 */
56
57 bool copy_data ( struct passwd* from, User& to )
58 {
59    to.clear();
60    if (!from) return false;
61    to.Name =       from->pw_name;
62    to.Password =   from->pw_passwd;
63    to.Uid =        from->pw_uid;
64    to.Gid =        from->pw_gid;
65    to.Gecos =      from->pw_gecos;
66    to.Homedir =    from->pw_dir;
67    to.Shell =      from->pw_shell;
68    return true;
69 } // eo copy_data(struct passwd*,Passwd&)
70
71
72 bool copy_data ( struct group* from , Group& to)
73 {
74    to.clear();
75    if (!from) return false;
76    to.Name =       from->gr_name;
77    to.Password =   from->gr_passwd;
78    to.Gid =        from->gr_gid;
79    to.Members.clear();
80    for ( char **ptr= from->gr_mem;
81          ptr && *ptr;
82          ++ptr)
83    {
84       to.Members.push_back ( *ptr );
85    }
86    return true;
87 } // eo copy_data(struct group*,Group&)
88
89
90 } // eo namespace <anonymous>
91
92
93 /*************************************************************************\
94 \*************************************************************************/
95
96 /*
97 ** implementation of User
98 */
99
100 User::User()
101 : Uid ((uid_t)-1)
102 , Gid ((gid_t)-1)
103 {
104 } // User::User()
105
106
107 /**
108  * @brief constructs and fills with user data.
109  * @param name the name of the user to search for.
110  */
111 User::User(const std::string& name)
112 {
113    get_user(name,*this);
114 } // eo User::User(const std::string&)
115
116
117 /**
118  * @brief constructs and fills with user data.
119  * @param name the name of the user to search for.
120  */
121 User::User(const char* name)
122 {
123    get_user(std::string (name),*this);
124 } // eo User::User(const char*)
125
126
127 /**
128  * @brief constructs and fills with user data.
129  * @param uid the uid of the user to search for.
130  */
131 User::User(uid_t uid)
132 {
133    get_user(uid,*this);
134    this->Uid = uid;
135 } // eo User::User(uid_t)
136
137
138
139 /**
140  * @brief clears the data.
141  */
142 void User::clear()
143 {
144    Name.clear();
145    Password.clear();
146    Uid= (uid_t)-1;
147    Gid= (gid_t)-1;
148    Gecos.clear();
149    Homedir.clear();
150    Shell.clear();
151 } // eo User::clear()
152
153
154 /**
155  * @brief returns if the structure content looks ok.
156  * @return @a true if the content looks ok.
157  *
158  * This functions checks if mandatory values are existing.
159  * @note It does not check if content is consistent with any system database!
160  */
161 bool User::is_valid() const
162 {
163    return (Uid != (uid_t)-1) and (Gid != (gid_t)-1)
164           and not Name.empty()
165           ;
166 } // eo User::is_valid() const
167
168
169 /*
170 ** implementation of Group
171 */
172
173
174 Group::Group()
175 : Gid ((gid_t)-1)
176 {
177 } // eo Group::Group()
178
179
180 /**
181  * @brief constructs and fills with group data.
182  * @param name the name of the group to search for.
183  */
184 Group::Group(const std::string& name)
185 {
186    get_group(name,*this);
187 } // eo group::Group(const std::strring&)
188
189
190 /**
191  * @brief constructs and fills with group data.
192  * @param name the name of the group to search for.
193  */
194 Group::Group(const char* name)
195 {
196    get_group(std::string (name),*this);
197 } // eo group::Group(const char*)
198
199
200 /**
201  * @brief constructs and fills with group data.
202  * @param gid the gid of the group to search for.
203  */
204 Group::Group(gid_t gid)
205 {
206    get_group(gid,*this);
207    this->Gid= gid;
208 } // eo Group::Group(gid_t);
209
210
211 /**
212  * @brief clears the data.
213  */
214 void Group::clear()
215 {
216    Name.clear();
217    Password.clear();
218    Gid= (gid_t)-1;
219    Members.clear();
220 } // eo Group::clear()
221
222
223 /**
224  * @brief returns if the structure content looks ok.
225  * @return @a true if the content looks ok.
226  *
227  * This functions checks if mandatory values are existing.
228  * @note It does not check if content is consistent with any system database!
229  */
230 bool Group::is_valid() const
231 {
232    return (Gid != (gid_t)-1) and not Name.empty();
233 } // eo Group::is_valid() const
234
235 /**
236  * @brief get the (system) user data by name.
237  * @param[in] name the name of the user to search for.
238  * @param[out] result the user info.
239  * @return @a true iff the user was found and the result structure contains data.
240  */
241 bool get_user(const std::string& name, User& result)
242 {
243    struct passwd pw;
244    struct passwd *pw_ptr= NULL;
245    size_t buffer_size= sysconf (_SC_GETPW_R_SIZE_MAX);
246    boost::scoped_array< char > buffer ( new char[ buffer_size ] );
247
248    int res= ::getpwnam_r(name.c_str(), &pw, buffer.get(), buffer_size, &pw_ptr);
249
250    if (not (0 == res) or not pw_ptr)
251    {
252       return false;
253    }
254
255    return copy_data(pw_ptr, result);
256 } // eo get_user(const std::string&,User&)
257
258
259 /**
260  * @brief get the (system) user data by uid.
261  * @param[in] uid the uid of the user to search for.
262  * @param[out] result the user info.
263  * @return @a true iff the user was found and the result structure contains data.
264  */
265 bool get_user(uid_t uid, User& result)
266 {
267    struct passwd pw;
268    struct passwd *pw_ptr= NULL;
269    size_t buffer_size= sysconf (_SC_GETPW_R_SIZE_MAX);
270    boost::scoped_array< char > buffer ( new char[ buffer_size ] );
271
272    int res= ::getpwuid_r(uid, &pw, buffer.get(), buffer_size, &pw_ptr);
273
274    if (not (0 == res) or not pw_ptr)
275    {
276       return false;
277    }
278
279    return copy_data(pw_ptr, result);
280 } // eo get_user(uid_t,User&)
281
282
283 /**
284  * @brief get user data by name.
285  * @param name name of the user
286  * @return the user data (invalid if user not found or on error).
287  */
288 User get_user(const std::string& name)
289 {
290    User result;
291    get_user(name,result);
292    return result;
293 } // eo get_user(const std::string&)
294
295
296 /**
297  * @brief get user data by uid.
298  * @param uid uid of the user
299  * @return the user data (invalid if user not found or on error).
300  */
301 User get_user(uid_t uid)
302 {
303    User result;
304    get_user(uid,result);
305    return result;
306 } // eo get_user(const std::string&)
307
308
309
310 /**
311  * @brief get the (system) group data by name.
312  * @param[in] name the name of the group to search for.
313  * @param[out] result the group info.
314  * @return @a true iff the group was found and the result structure contains data.
315  */
316 bool get_group (const std::string& name, Group& result)
317 {
318    struct group gr;
319    struct group *gr_ptr= NULL;
320    size_t buffer_size= sysconf (_SC_GETGR_R_SIZE_MAX);
321    boost::scoped_array< char > buffer ( new char[ buffer_size ] );
322
323    int res= ::getgrnam_r(name.c_str(), &gr, buffer.get(), buffer_size, &gr_ptr);
324
325    if (not (0 == res) or not gr_ptr)
326    {
327       return false;
328    }
329
330    return copy_data(gr_ptr, result);
331 } // eo get_group(const std::string&,Group&)
332
333
334 /**
335  * @brief get the (system) group data by gid.
336  * @param[in] gid the gid of the group to search for.
337  * @param[out] result the group info.
338  * @return @a true iff the group was found and the result structure contains data.
339  */
340 bool get_group(gid_t gid, Group& result)
341 {
342    struct group gr;
343    struct group *gr_ptr= NULL;
344    size_t buffer_size= sysconf (_SC_GETGR_R_SIZE_MAX);
345    boost::scoped_array< char > buffer ( new char[ buffer_size ] );
346
347    int res= ::getgrgid_r(gid, &gr, buffer.get(), buffer_size, &gr_ptr);
348
349    if (not (0 == res) or not gr_ptr)
350    {
351       return false;
352    }
353
354    return copy_data(gr_ptr, result);
355 } // eo get_group(const std::string&,Group&)
356
357
358 /**
359  * @brief get group data by name.
360  * @param name name of the group
361  * @return the group data (invalid if group not found or on error).
362  */
363 Group get_group(const std::string& name)
364 {
365    Group result;
366    get_group(name, result);
367    return result;
368 } // eo get_group(const std::string&)
369
370
371 /**
372  * @brief get group data by gid.
373  * @param gid gid of the group
374  * @return the group data (invalid if group not found or on error).
375  */
376 Group get_group(gid_t gid)
377 {
378    Group result;
379    get_group(gid, result);
380    return result;
381 } // eo get_group(const std::string&)
382
383 } // eo namespace I2n