constinfo for unittest too
[xapian.git] / xapian-applications / omega / unixperm.cc
blob0d639e1e33534b3db8b94cf38ca9501ef40fe83e
1 /** @file unixperm.cc
2 * @brief Filter results according to Unix-style access permissions
3 */
4 /* Copyright (C) 2010 Olly Betts
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <config.h>
23 #include "unixperm.h"
25 #include "safeerrno.h"
26 #include <sys/types.h>
27 #include <grp.h>
28 #include <pwd.h>
29 #include "safeunistd.h"
31 #include <cstring>
33 #ifdef GETGROUPLIST_TAKES_INT_P
34 # define GID_T int
35 #else
36 # define GID_T gid_t
37 #endif
39 using namespace std;
41 void
42 apply_unix_permissions(Xapian::Query & query, const char * user)
44 // Apply permission filters.
45 vector<string> allow;
46 vector<string> deny;
47 allow.push_back("I*");
48 allow.push_back(string("I@") + user);
49 deny.push_back(string("V@") + user);
51 struct passwd * pwent = getpwnam(user);
52 if (!pwent) {
53 query = Xapian::Query();
54 return;
57 // Add supplementary groups for user too.
58 #ifdef HAVE_GETGROUPLIST
59 int ngroups = 32;
61 GID_T *groups = new GID_T[ngroups];
63 while (getgrouplist(user, pwent->pw_gid, groups, &ngroups) == -1) {
64 delete [] groups;
65 groups = new GID_T[ngroups];
68 for (int i = 0; i < ngroups; ++i) {
69 struct group * grentry = getgrgid(groups[i]);
70 if (grentry) {
71 const char * group = grentry->gr_name;
72 allow.push_back(string("I#") + group);
73 deny.push_back(string("V#") + group);
76 #else
77 gid_t main_gid = pwent->pw_gid;
78 struct group * grentry = getgrgid(pwent->pw_gid);
79 if (grentry) {
80 const char * group = grentry->gr_name;
81 allow.push_back(string("I#") + group);
82 deny.push_back(string("V#") + group);
85 // Make sure we're rewound.
86 setgrent();
87 errno = 0;
88 while ((grentry = getgrent()) != NULL) {
89 // Don't process the main group again if it happens to be listed as
90 // a supplementary group.
91 if (grentry->gr_gid == main_gid)
92 continue;
93 for (char ** members = grentry->gr_mem; *members; ++members) {
94 if (strcmp(*members, user) == 0) {
95 const char * group = grentry->gr_name;
96 allow.push_back(string("I#") + group);
97 deny.push_back(string("V#") + group);
98 break;
102 if (errno) {
103 // FIXME: handle?
105 endgrent();
106 #endif
108 query = Xapian::Query(query.OP_FILTER,
109 query,
110 Xapian::Query(query.OP_OR,
111 allow.begin(),
112 allow.end()));
113 query = Xapian::Query(query.OP_AND_NOT,
114 query,
115 Xapian::Query(query.OP_OR,
116 deny.begin(),
117 deny.end()));