00001 /* 00002 * Copyright (c) Members of the EGEE Collaboration. 2006-2010. 00003 * See http://www.eu-egee.org/partners/ for details on the copyright holders. 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /************* 00019 * Simple Argus PEP client example 00020 * 00021 * gcc -I/usr/include -L/usr/lib64 -largus-pep pep_client_example.c -o pep_client_example 00022 * 00023 * or use "pkg-config libargus-pep --cflags --libs" to dertermine the required CFLAGS and 00024 * LDFLAGS. 00025 * 00026 * Author: Valery Tschopp <valery.tschopp@switch.ch> 00027 * $Id: pep_client_example.c 2481 2011-09-28 15:05:53Z vtschopp $ 00028 ************/ 00029 00030 #include <stdio.h> 00031 #include <stdlib.h> 00032 00033 /* include Argus PEP client API header */ 00034 #include <argus/pep.h> 00035 00036 /* prototypes */ 00037 static int create_xacml_request(xacml_request_t ** request,const char * subjectid, const char * resourceid, const char * actionid); 00038 static int process_xacml_response(const xacml_response_t * response); 00039 static const char * decision_tostring(xacml_decision_t decision); 00040 static const char * fulfillon_tostring(xacml_fulfillon_t fulfillon); 00041 00042 /* 00043 * main 00044 */ 00045 int main(void) { 00046 00047 /* Argus PEP client handle */ 00048 PEP * pep; 00049 00050 /* functions return code */ 00051 pep_error_t pep_rc; /* PEP function error */ 00052 int rc; /* others functions */ 00053 00054 /* XACML request and response */ 00055 xacml_request_t * request; 00056 xacml_response_t * response; 00057 00058 char * pep_url, * subjectid, * resourceid, * actionid; 00059 00060 /* dump library version */ 00061 fprintf(stdout,"using %s\n",pep_version()); 00062 00063 00064 /* create the PEP client handle */ 00065 pep= pep_initialize(); 00066 if (pep == NULL) { 00067 fprintf(stderr,"failed to create PEP client\n"); 00068 exit(1); 00069 } 00070 00071 /* debugging options */ 00072 pep_setoption(pep,PEP_OPTION_LOG_STDERR,stderr); 00073 pep_setoption(pep,PEP_OPTION_LOG_LEVEL,PEP_LOGLEVEL_DEBUG); 00074 00075 /* configure PEP client: PEP Server endpoint url */ 00076 pep_url= "https://chaos.switch.ch:8154/authz"; 00077 pep_rc= pep_setoption(pep,PEP_OPTION_ENDPOINT_URL,pep_url); 00078 if (pep_rc != PEP_OK) { 00079 fprintf(stderr,"failed to set PEP endpoint: %s: %s\n", pep_url, pep_strerror(pep_rc)); 00080 exit(1); 00081 } 00082 /* configure PEP client: private key and certificate required to access the PEP Server */ 00083 /* endpoint (HTTPS with client authentication) */ 00084 pep_rc= pep_setoption(pep,PEP_OPTION_ENDPOINT_CLIENT_KEY,"/etc/grid-security/hostkey.pem"); 00085 if (pep_rc != PEP_OK) { 00086 fprintf(stderr,"failed to set client key: %s: %s\n", "/etc/grid-security/hostkey.pem", pep_strerror(pep_rc)); 00087 exit(1); 00088 } 00089 pep_rc= pep_setoption(pep,PEP_OPTION_ENDPOINT_CLIENT_CERT,"/etc/grid-security/hostcert.pem"); 00090 if (pep_rc != PEP_OK) { 00091 fprintf(stderr,"failed to set client cert: %s: %s\n", "/etc/grid-security/hostcert.pem", pep_strerror(pep_rc)); 00092 exit(1); 00093 } 00094 /* server certificate CA path for validation */ 00095 pep_rc= pep_setoption(pep,PEP_OPTION_ENDPOINT_SERVER_CAPATH,"/etc/grid-security/certificates"); 00096 if (pep_rc != PEP_OK) { 00097 fprintf(stderr,"failed to set server CA path: %s: %s\n", "/etc/grid-security/certificates", pep_strerror(pep_rc)); 00098 exit(1); 00099 } 00100 00101 /* create the XACML request */ 00102 subjectid= "CN=Valery Tschopp 9FEE5EE3,O=Switch - Teleinformatikdienste fuer Lehre und Forschung,DC=slcs,DC=switch,DC=ch"; 00103 resourceid= "switch"; 00104 actionid= "switch"; 00105 rc= create_xacml_request(&request,subjectid,resourceid,actionid); 00106 if (rc != 0) { 00107 fprintf(stderr,"failed to create XACML request\n"); 00108 exit(1); 00109 } 00110 00111 /* submit the XACML request */ 00112 pep_rc= pep_authorize(pep,&request, &response); 00113 if (pep_rc != PEP_OK) { 00114 fprintf(stderr,"failed to authorize XACML request: %s\n", pep_strerror(pep_rc)); 00115 exit(1); 00116 } 00117 00118 /* parse and process XACML response */ 00119 rc= process_xacml_response(response); 00120 00121 /* delete resquest and response objs */ 00122 xacml_request_delete(request); 00123 xacml_response_delete(response); 00124 00125 /* release the PEP client handle */ 00126 pep_destroy(pep); 00127 00128 return 0; 00129 } 00130 00131 /* 00132 * Creates a XACML Request containing a XACML Subject with the given subjectid, a XACML Resource 00133 * with the given resourceid and a XACML Action with the given actionid. 00134 * 00135 * @param [in/out] request address of the pointer to the XACML request object 00136 * @param [in] subjectid, a X.509 DN, attribute value of the XACML Request/Subject element 00137 * @param [in] resourceid attribute value of the XACML Request/Resource element 00138 * @param [in] actionid attribute value of the XACML Request/Action element 00139 * @return 0 on success or error code on failure. 00140 */ 00141 static int create_xacml_request(xacml_request_t ** request,const char * subjectid, const char * resourceid, const char * actionid) 00142 { 00143 xacml_subject_t * subject; 00144 xacml_attribute_t * subject_attr_id; 00145 xacml_resource_t * resource; 00146 xacml_attribute_t * resource_attr_id; 00147 xacml_action_t * action; 00148 xacml_attribute_t * action_attr_id; 00149 00150 /* XACML Subject with subjectid Attribute value */ 00151 subject= xacml_subject_create(); 00152 if (subject == NULL) { 00153 fprintf(stderr,"can not create XACML Subject\n"); 00154 return 1; 00155 } 00156 subject_attr_id= xacml_attribute_create(XACML_SUBJECT_ID); 00157 if (subject_attr_id == NULL) { 00158 fprintf(stderr,"can not create XACML Subject/Attribute:%s\n",XACML_SUBJECT_ID); 00159 xacml_subject_delete(subject); 00160 return 1; 00161 } 00162 // set X.509 DN value 00163 xacml_attribute_addvalue(subject_attr_id,subjectid); 00164 // set attribute datatype for X.509 DN 00165 xacml_attribute_setdatatype(subject_attr_id,XACML_DATATYPE_X500NAME); 00166 xacml_subject_addattribute(subject,subject_attr_id); 00167 00168 /* XACML Resource with resourceid Attribute value */ 00169 resource= xacml_resource_create(); 00170 if (resource == NULL) { 00171 fprintf(stderr,"can not create XACML Resource\n"); 00172 xacml_subject_delete(subject); 00173 return 2; 00174 } 00175 resource_attr_id= xacml_attribute_create(XACML_RESOURCE_ID); 00176 if (resource_attr_id == NULL) { 00177 fprintf(stderr,"can not create XACML Resource/Attribute:%s\n",XACML_RESOURCE_ID); 00178 xacml_subject_delete(subject); 00179 xacml_resource_delete(resource); 00180 return 2; 00181 } 00182 xacml_attribute_addvalue(resource_attr_id,resourceid); 00183 xacml_resource_addattribute(resource,resource_attr_id); 00184 00185 /* XACML Action with actionid Attribute value */ 00186 action= xacml_action_create(); 00187 if (action == NULL) { 00188 fprintf(stderr,"can not create XACML Action\n"); 00189 xacml_subject_delete(subject); 00190 xacml_resource_delete(resource); 00191 return 3; 00192 } 00193 action_attr_id= xacml_attribute_create(XACML_ACTION_ID); 00194 if (action_attr_id == NULL) { 00195 fprintf(stderr,"can not create XACML Action/Attribute:%s\n",XACML_ACTION_ID); 00196 xacml_subject_delete(subject); 00197 xacml_resource_delete(resource); 00198 xacml_action_delete(action); 00199 return 3; 00200 } 00201 xacml_attribute_addvalue(action_attr_id,actionid); 00202 xacml_action_addattribute(action,action_attr_id); 00203 00204 /* XACML Request with all elements */ 00205 *request= xacml_request_create(); 00206 if (*request == NULL) { 00207 fprintf(stderr,"can not create XACML Request\n"); 00208 xacml_subject_delete(subject); 00209 xacml_resource_delete(resource); 00210 xacml_action_delete(action); 00211 return 4; 00212 } 00213 xacml_request_addsubject(*request,subject); 00214 xacml_request_addresource(*request,resource); 00215 xacml_request_setaction(*request,action); 00216 00217 return 0; 00218 } 00219 00220 /* 00221 * Simply dump the XACML response. 00222 * 00223 * @param [in] response the XAXML response 00224 * @return 0 on success or error code on failure. 00225 */ 00226 static int process_xacml_response(const xacml_response_t * response) { 00227 size_t results_l; 00228 int i, j, k; 00229 if (response == NULL) { 00230 fprintf(stderr,"response is NULL\n"); 00231 return 1; 00232 } 00233 results_l= xacml_response_results_length(response); 00234 fprintf(stdout,"response: %d results\n", (int)results_l); 00235 for(i= 0; i<results_l; i++) { 00236 xacml_result_t * result; 00237 xacml_status_t * status; 00238 xacml_statuscode_t * statuscode, * subcode; 00239 size_t obligations_l; 00240 00241 result= xacml_response_getresult(response,i); 00242 fprintf(stdout,"response.result[%d].decision= %s\n", i, decision_tostring(xacml_result_getdecision(result))); 00243 fprintf(stdout,"response.result[%d].resourceid= %s\n", i, xacml_result_getresourceid(result)); 00244 00245 status= xacml_result_getstatus(result); 00246 fprintf(stdout,"response.result[%d].status.message= %s\n", i, xacml_status_getmessage(status)); 00247 statuscode= xacml_status_getcode(status); 00248 fprintf(stdout,"response.result[%d].status.code.value= %s\n", i, xacml_statuscode_getvalue(statuscode)); 00249 subcode= xacml_statuscode_getsubcode(statuscode); 00250 if (subcode != NULL) { 00251 fprintf(stdout,"response.result[%d].status.code.subcode.value= %s\n", i, xacml_statuscode_getvalue(subcode)); 00252 } 00253 obligations_l= xacml_result_obligations_length(result); 00254 fprintf(stdout,"response.result[%d]: %d obligations\n", i, (int)obligations_l); 00255 for(j= 0; j<obligations_l; j++) { 00256 size_t attrs_l; 00257 xacml_obligation_t * obligation= xacml_result_getobligation(result,j); 00258 fprintf(stdout,"response.result[%d].obligation[%d].id= %s\n",i,j, xacml_obligation_getid(obligation)); 00259 fprintf(stdout,"response.result[%d].obligation[%d].fulfillOn= %s\n",i,j, fulfillon_tostring(xacml_obligation_getfulfillon(obligation))); 00260 attrs_l= xacml_obligation_attributeassignments_length(obligation); 00261 fprintf(stdout,"response.result[%d].obligation[%d]: %d attribute assignments\n",i,j,(int)attrs_l); 00262 for (k= 0; k<attrs_l; k++) { 00263 xacml_attributeassignment_t * attr= xacml_obligation_getattributeassignment(obligation,k); 00264 fprintf(stdout,"response.result[%d].obligation[%d].attributeassignment[%d].id= %s\n",i,j,k,xacml_attributeassignment_getid(attr)); 00265 fprintf(stdout,"response.result[%d].obligation[%d].attributeassignment[%d].datatype= %s\n",i,j,k,xacml_attributeassignment_getdatatype(attr)); 00266 fprintf(stdout,"response.result[%d].obligation[%d].attributeassignment[%d].value= %s\n",i,j,k,xacml_attributeassignment_getvalue(attr)); 00267 } 00268 } 00269 } 00270 return 0; 00271 } 00272 00273 /* 00274 * Returns the string representation of the decision. 00275 */ 00276 static const char * decision_tostring(xacml_decision_t decision) { 00277 switch(decision) { 00278 case XACML_DECISION_DENY: 00279 return "Deny"; 00280 break; 00281 case XACML_DECISION_PERMIT: 00282 return "Permit"; 00283 break; 00284 case XACML_DECISION_INDETERMINATE: 00285 return "Indeterminate"; 00286 break; 00287 case XACML_DECISION_NOT_APPLICABLE: 00288 return "Not Applicable"; 00289 break; 00290 default: 00291 return "ERROR (Unknown Decision)"; 00292 break; 00293 } 00294 } 00295 00296 /* 00297 * Returns the string representation of the fulfillOn. 00298 */ 00299 static const char * fulfillon_tostring(xacml_fulfillon_t fulfillon) { 00300 switch(fulfillon) { 00301 case XACML_FULFILLON_DENY: 00302 return "Deny"; 00303 break; 00304 case XACML_FULFILLON_PERMIT: 00305 return "Permit"; 00306 break; 00307 default: 00308 return "ERROR (Unknown FulfillOn)"; 00309 break; 00310 } 00311 }