~ubuntu-branches/debian/sid/nordugrid-arc/sid

« back to all changes in this revision

Viewing changes to .pc/nordugrid-arc-unistd.patch/src/services/a-rex/grid-manager/arc_vomsac_check.cpp

  • Committer: Package Import Robot
  • Author(s): Mattias Ellert
  • Date: 2012-12-13 16:41:31 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20121213164131-0fumka0jar8mxm07
Tags: 2.0.1-1
* 2.0.1 Release
* Drop patches accepted upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#ifdef HAVE_CONFIG_H
2
 
#include <config.h>
3
 
#endif
4
 
 
5
 
#include <iostream>
6
 
#include <fstream>
7
 
#include <sys/stat.h>
8
 
 
9
 
#include <arc/Logger.h>
10
 
#include <arc/IString.h>
11
 
#include <arc/StringConv.h>
12
 
#include <arc/IniConfig.h>
13
 
#include <arc/ArcRegex.h>
14
 
#include <arc/credential/Credential.h>
15
 
#include <arc/credential/VOMSUtil.h>
16
 
#include <arc/credential/VOMSAttribute.h>
17
 
 
18
 
#define AC_POLICY_PARAM_NAME "ac_policy"
19
 
 
20
 
static Arc::Logger logger(Arc::Logger::rootLogger, "arc-vomsac-check");
21
 
 
22
 
static void usage(char *pname) {
23
 
        logger.msg(Arc::ERROR,"Usage: %s [-N] -P <user proxy> -L <job status file> [-c <configfile>] [-d <loglevel>]",pname);
24
 
}
25
 
 
26
 
/* ARC classes use '/VO=voname/Group=groupname/subgroupname/Role=role' notation
27
 
 * VOMS classes use '/voname/groupname/subgroupname/Role=role/Capability=NULL' notation
28
 
 * For configuration compatibility reasons normalization to common format used
29
 
 * either for values provided in config or retreived from proxy certificate
30
 
 */
31
 
std::string normalize_fqan(std::string fqan) {
32
 
        // first trim possible spaces and quotes
33
 
        std::string nfqan = Arc::trim(fqan," \"");
34
 
        // remove 'VO=' and 'Group=' if any
35
 
        std::size_t pos = nfqan.find("VO=");
36
 
        if(pos != std::string::npos) nfqan.erase(pos, 3);
37
 
        pos = nfqan.find("Group=");
38
 
        if(pos != std::string::npos) nfqan.erase(pos, 6);
39
 
        // remove NULL values
40
 
        pos = nfqan.find("/Role=NULL");
41
 
        if(pos != std::string::npos) nfqan.erase(pos, 10);
42
 
        pos = nfqan.find("/Capability=NULL");
43
 
        if(pos != std::string::npos) nfqan.erase(pos, 16);
44
 
        // return normalized fqan
45
 
        return nfqan;   
46
 
}
47
 
 
48
 
int main(int argc, char *argv[]) {
49
 
        int opt;
50
 
        int no_ac_success = 0;
51
 
        const char *user_proxy_f = NULL;
52
 
        const char *job_local_f = NULL;
53
 
        const char *config_f = NULL;
54
 
 
55
 
        // log
56
 
        Arc::LogStream logcerr(std::cerr);
57
 
        Arc::Logger::getRootLogger().addDestination(logcerr);
58
 
        Arc::Logger::getRootLogger().setThreshold(Arc::ERROR);
59
 
 
60
 
        // parse options 
61
 
        while ((opt = getopt(argc, argv, "NP:L:c:d:")) != -1) {
62
 
                switch (opt) {
63
 
                        case 'N':
64
 
                                no_ac_success = 1;
65
 
                                break;
66
 
                        case 'P':
67
 
                                user_proxy_f = optarg;
68
 
                                break;
69
 
                        case 'L':
70
 
                                job_local_f = optarg;
71
 
                                break;
72
 
                        case 'c':
73
 
                                config_f = optarg;
74
 
                                break;
75
 
                        case 'd':
76
 
                                Arc::Logger::getRootLogger().setThreshold(
77
 
                                        Arc::old_level_to_level(atoi(optarg))
78
 
                                );
79
 
                                break;
80
 
                        default:
81
 
                                usage(argv[0]);
82
 
                                return EXIT_FAILURE;
83
 
                }
84
 
        }
85
 
        
86
 
 
87
 
        // check required
88
 
        if ( !user_proxy_f ) {
89
 
                logger.msg(Arc::ERROR,"User proxy file is required but is not specified");
90
 
                usage(argv[0]);
91
 
                return EXIT_FAILURE;
92
 
        }
93
 
        if ( !job_local_f ) {
94
 
                logger.msg(Arc::ERROR,"Local job status file is required");
95
 
                usage(argv[0]);
96
 
                return EXIT_FAILURE;
97
 
        }
98
 
        if ( !config_f ) {
99
 
                config_f = "/etc/arc.conf";
100
 
        }
101
 
 
102
 
        // read information about the job used by the A-REX
103
 
        // and determine selected queue
104
 
        std::string queue;
105
 
        std::ifstream job_local;
106
 
        job_local.open(job_local_f, std::ios::in);
107
 
        if ( job_local.is_open() ) {
108
 
                std::string line;
109
 
                while ( ! job_local.eof() ){
110
 
                        getline(job_local,line);
111
 
                        if ( ! line.compare(0,6,"queue=") ) {
112
 
                                queue = line.substr(6);
113
 
                                logger.msg(Arc::INFO,"Making the decision for the queue %s",queue);
114
 
                                break;
115
 
                        }
116
 
                }
117
 
        } else {
118
 
                logger.msg(Arc::ERROR,"Can not read information from the local job status file");
119
 
                return EXIT_FAILURE;
120
 
        }
121
 
        job_local.close();
122
 
 
123
 
        // Parse INI configuraion file
124
 
        Arc::IniConfig cfg(config_f);
125
 
        if ( ! cfg ) {
126
 
                logger.msg(Arc::ERROR,"Can not parse the configuration file %s",config_f);
127
 
                return EXIT_FAILURE;
128
 
        }
129
 
        
130
 
        // get queue ac_policy 
131
 
        // first try [queue/name] block directly, then search for 'id' or 'name' field in [queue] blocks
132
 
        std::string qqueue = '"' + queue + '"';
133
 
        Arc::XMLNode qparams = cfg["queue/" + queue];
134
 
        if ( ! (bool)qparams ) {
135
 
                for(Arc::XMLNode qnode = cfg["queue"];(bool)qnode;++qnode) {
136
 
                        if ( (std::string)qnode["id"] == qqueue || (std::string)qnode["name"] == qqueue ) {
137
 
                                qparams = qnode;
138
 
                                break;
139
 
                        }
140
 
                }
141
 
        }
142
 
        if ( ! (bool)qparams) {
143
 
                logger.msg(Arc::ERROR,"Can not find queue '%s' in the configuration file",queue);
144
 
                return EXIT_FAILURE;
145
 
        }
146
 
 
147
 
        // create match regexes from ac_policy provided
148
 
        std::vector< std::pair<Arc::RegularExpression,bool> > access_policies;
149
 
        for ( Arc::XMLNode pnode = qparams[AC_POLICY_PARAM_NAME];(bool)pnode;++pnode) {
150
 
                std::string acp = (std::string)pnode;
151
 
                std::size_t pos = acp.find("VOMS:");
152
 
                if ( pos != std::string::npos ) {
153
 
                        // determine positive/negative match
154
 
                        bool pmatch = true;
155
 
                        if ( pos ) { 
156
 
                                char pnflag = acp[pos-1];
157
 
                                if ( pnflag == '-' || pnflag == '!' ) pmatch = false;
158
 
                        }
159
 
                        // normalize rest part of the string 
160
 
                        std::string regex = ".*" + normalize_fqan(acp.substr(pos + 5)) + ".*";
161
 
                        // save (regex,pmatch) pairs to access_policies vector
162
 
                        std::pair <Arc::RegularExpression,bool> match_regex(Arc::RegularExpression(regex),pmatch);
163
 
                        access_policies.push_back(match_regex);
164
 
                }
165
 
        }
166
 
        if ( access_policies.empty() ) {
167
 
                logger.msg(Arc::INFO,"No access policy to check, returning success");
168
 
                return EXIT_SUCCESS;
169
 
        }
170
 
 
171
 
        struct stat statFInfo;
172
 
 
173
 
        // CA Cert directory required to work with proxy
174
 
        std::string ca_dir = (std::string)cfg["common"]["x509_cert_dir"];
175
 
        if (ca_dir.empty()) {
176
 
                ca_dir = "/etc/grid-security/certificates";
177
 
        } else {
178
 
                ca_dir = Arc::trim(ca_dir,"\"");
179
 
        }
180
 
        if ( stat(ca_dir.c_str(),&statFInfo) ) {
181
 
                logger.msg(Arc::ERROR,"CA certificates directory %s does not exist", ca_dir);
182
 
                return EXIT_FAILURE;
183
 
        }
184
 
 
185
 
        // VOMS directory required to verify VOMS ACs
186
 
        std::string voms_dir = (std::string)cfg["common"]["x509_voms_dir"];
187
 
        if (voms_dir.empty()) {
188
 
                voms_dir = "/etc/grid-security/vomsdir";
189
 
        } else {
190
 
                voms_dir = Arc::trim(voms_dir,"\"");
191
 
        }
192
 
        // Or maybe not _required_
193
 
        //if ( stat(voms_dir.c_str(),&statFInfo) ) {
194
 
        //      logger.msg(Arc::ERROR,"VOMS directory %s does not exist", voms_dir);
195
 
        //      return EXIT_FAILURE;
196
 
        //}
197
 
 
198
 
        // construct ARC credentials object
199
 
        Arc::Credential holder(user_proxy_f, "", ca_dir, "");
200
 
        if (! holder.GetVerification()) {
201
 
                logger.msg(Arc::ERROR,"User proxy certificate is not valid");
202
 
                return EXIT_FAILURE;
203
 
        }
204
 
 
205
 
        // get VOMS AC from proxy certificate
206
 
        logger.msg(Arc::DEBUG,"Getting VOMS AC for: %s", holder.GetDN());
207
 
        std::vector<Arc::VOMSACInfo> voms_attributes;
208
 
        Arc::VOMSTrustList vomscert_trust_dn;
209
 
        vomscert_trust_dn.AddRegex(".*");
210
 
 
211
 
        if ( ! Arc::parseVOMSAC(holder, ca_dir, "", voms_dir, vomscert_trust_dn, voms_attributes, true, true) ) {
212
 
                // logger.msg(Arc::WARNING,"Error parsing VOMS AC");
213
 
                if ( no_ac_success ) return EXIT_SUCCESS;
214
 
                return EXIT_FAILURE;
215
 
        }
216
 
 
217
 
        // loop over access_policies
218
 
        for (std::vector<std::pair<Arc::RegularExpression,bool> >::iterator iP = access_policies.begin();
219
 
                iP != access_policies.end(); iP++) {
220
 
                logger.msg(Arc::VERBOSE,"Checking a match for '%s'",(iP->first).getPattern());
221
 
                // for every VOMS AC provided
222
 
                for (std::vector<Arc::VOMSACInfo>::iterator iAC = voms_attributes.begin(); iAC != voms_attributes.end(); iAC++) {
223
 
                        // check every attribure specified to match specified policy
224
 
                        for (int acnt = 0; acnt < iAC->attributes.size(); acnt++ ) {
225
 
                                std::string fqan = normalize_fqan(iAC->attributes[acnt]);
226
 
                                if ( (iP->first).match(fqan) ) {
227
 
                                        logger.msg(Arc::DEBUG,"FQAN '%s' IS a match to '%s'",fqan,(iP->first).getPattern());
228
 
                                        // if positive match return success
229
 
                                        if ( iP->second ) return EXIT_SUCCESS;
230
 
                                        // prohibit execution on negative match
231
 
                                        logger.msg(Arc::ERROR,"Queue '%s' usage is prohibited to FQAN '%s' by the site access policy",
232
 
                                                queue, fqan);
233
 
                                        return EXIT_FAILURE;
234
 
                                } else {
235
 
                                        logger.msg(Arc::DEBUG,"FQAN '%s' IS NOT a match to '%s'",fqan,(iP->first).getPattern());
236
 
                                }
237
 
                        }
238
 
                }
239
 
        }
240
 
 
241
 
        logger.msg(Arc::ERROR,"Queue '%s' usage with provided FQANs is prohibited by the site access policy",queue);
242
 
        return EXIT_FAILURE;
243
 
}
244