pep_client_example.c

This is an example how to use the PEP client.

/*
 * Copyright (c) Members of the EGEE Collaboration. 2006-2010.
 * See http://www.eu-egee.org/partners/ for details on the copyright holders.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*************
 * Simple Argus PEP client example
 *
 * gcc -I/usr/include -L/usr/lib64 -largus-pep pep_client_example.c -o pep_client_example
 *
 * or use "pkg-config libargus-pep --cflags --libs" to dertermine the required CFLAGS and 
 * LDFLAGS.
 *
 * Author: Valery Tschopp <valery.tschopp@switch.ch>
 * $Id$
 ************/

#include <stdio.h>
#include <stdlib.h>

/* include Argus PEP client API header */
#include <argus/pep.h>

/* prototypes */
static int create_xacml_request(xacml_request_t ** request,const char * subjectid, const char * resourceid, const char * actionid);
static int process_xacml_response(const xacml_response_t * response);
static const char * decision_tostring(xacml_decision_t decision);
static const char * fulfillon_tostring(xacml_fulfillon_t fulfillon);

/*
 * main
 */
int main(void) {

    /* Argus PEP client handle */
    PEP * pep;

    /* functions return code */
    pep_error_t pep_rc; /* PEP function error */
    int rc;             /* others functions */
    
    /* XACML request and response */
    xacml_request_t * request;
    xacml_response_t * response;

    char * pep_url, * subjectid, * resourceid, * actionid;

    /* dump library version */
    fprintf(stdout,"using %s\n",pep_version());

    
    /* create the PEP client handle */
    pep= pep_initialize();
    if (pep == NULL) {
       fprintf(stderr,"failed to create PEP client\n");
       exit(1);
    }

    /* debugging options */
    pep_setoption(pep,PEP_OPTION_LOG_STDERR,stderr);
    pep_setoption(pep,PEP_OPTION_LOG_LEVEL,PEP_LOGLEVEL_DEBUG);

    /* configure PEP client: PEP Server endpoint url */
    pep_url= "https://chaos.switch.ch:8154/authz";
    pep_rc= pep_setoption(pep,PEP_OPTION_ENDPOINT_URL,pep_url);
    if (pep_rc != PEP_OK) {
       fprintf(stderr,"failed to set PEP endpoint: %s: %s\n", pep_url, pep_strerror(pep_rc));
       exit(1);
    }   
    /* configure PEP client: private key and certificate required to access the PEP Server */
    /* endpoint (HTTPS with client authentication) */
    pep_rc= pep_setoption(pep,PEP_OPTION_ENDPOINT_CLIENT_KEY,"/etc/grid-security/hostkey.pem");
    if (pep_rc != PEP_OK) {
       fprintf(stderr,"failed to set client key: %s: %s\n", "/etc/grid-security/hostkey.pem", pep_strerror(pep_rc));
       exit(1);
    }   
    pep_rc= pep_setoption(pep,PEP_OPTION_ENDPOINT_CLIENT_CERT,"/etc/grid-security/hostcert.pem");
    if (pep_rc != PEP_OK) {
       fprintf(stderr,"failed to set client cert: %s: %s\n", "/etc/grid-security/hostcert.pem", pep_strerror(pep_rc));
       exit(1);
    }   
    /* server certificate CA path for validation */
    pep_rc= pep_setoption(pep,PEP_OPTION_ENDPOINT_SERVER_CAPATH,"/etc/grid-security/certificates");
    if (pep_rc != PEP_OK) {
       fprintf(stderr,"failed to set server CA path: %s: %s\n", "/etc/grid-security/certificates", pep_strerror(pep_rc));
       exit(1);
    }   

    /* create the XACML request */
    subjectid= "CN=Valery Tschopp 9FEE5EE3,O=Switch - Teleinformatikdienste fuer Lehre und Forschung,DC=slcs,DC=switch,DC=ch";
    resourceid= "switch";
    actionid= "switch";
    rc= create_xacml_request(&request,subjectid,resourceid,actionid);
    if (rc != 0) {
       fprintf(stderr,"failed to create XACML request\n");
       exit(1);
    }

    /* submit the XACML request */
    pep_rc= pep_authorize(pep,&request, &response);
    if (pep_rc != PEP_OK) {
       fprintf(stderr,"failed to authorize XACML request: %s\n", pep_strerror(pep_rc));
       exit(1);
    }   
    
    /* parse and process XACML response */
    rc= process_xacml_response(response);
    
    /* delete resquest and response objs */
    xacml_request_delete(request);
    xacml_response_delete(response);
        
    /* release the PEP client handle */
    pep_destroy(pep);

    return 0;
}

/*
 * Creates a XACML Request containing a XACML Subject with the given subjectid, a XACML Resource
 * with the given resourceid and a XACML Action with the given actionid.
 * 
 * @param [in/out] request address of the pointer to the XACML request object
 * @param [in] subjectid, a X.509 DN, attribute value of the XACML Request/Subject element 
 * @param [in] resourceid  attribute value of the XACML Request/Resource element
 * @param [in] actionid  attribute value of the XACML Request/Action element
 * @return 0 on success or error code on failure.
 */
static int create_xacml_request(xacml_request_t ** request,const char * subjectid, const char * resourceid, const char * actionid)
{
    xacml_subject_t * subject;
    xacml_attribute_t * subject_attr_id;
    xacml_resource_t * resource;
    xacml_attribute_t * resource_attr_id;
    xacml_action_t * action;
    xacml_attribute_t * action_attr_id;
    
    /* XACML Subject with subjectid Attribute value */
    subject= xacml_subject_create();
    if (subject == NULL) {
        fprintf(stderr,"can not create XACML Subject\n");
        return 1;
    }
    subject_attr_id= xacml_attribute_create(XACML_SUBJECT_ID);
    if (subject_attr_id == NULL) {
        fprintf(stderr,"can not create XACML Subject/Attribute:%s\n",XACML_SUBJECT_ID);
        xacml_subject_delete(subject);
        return 1;
    }
    // set X.509 DN value
    xacml_attribute_addvalue(subject_attr_id,subjectid);
    // set attribute datatype for X.509 DN
    xacml_attribute_setdatatype(subject_attr_id,XACML_DATATYPE_X500NAME); 
    xacml_subject_addattribute(subject,subject_attr_id);

    /* XACML Resource with resourceid Attribute value */
    resource= xacml_resource_create();
    if (resource == NULL) {
        fprintf(stderr,"can not create XACML Resource\n");
        xacml_subject_delete(subject);
        return 2;
    }
    resource_attr_id= xacml_attribute_create(XACML_RESOURCE_ID);
    if (resource_attr_id == NULL) {
        fprintf(stderr,"can not create XACML Resource/Attribute:%s\n",XACML_RESOURCE_ID);
        xacml_subject_delete(subject);
        xacml_resource_delete(resource);
        return 2;
    }
    xacml_attribute_addvalue(resource_attr_id,resourceid);
    xacml_resource_addattribute(resource,resource_attr_id);

    /* XACML Action with actionid Attribute value */
    action= xacml_action_create();
    if (action == NULL) {
        fprintf(stderr,"can not create XACML Action\n");
        xacml_subject_delete(subject);
        xacml_resource_delete(resource);
        return 3;
    }
    action_attr_id= xacml_attribute_create(XACML_ACTION_ID);
    if (action_attr_id == NULL) {
        fprintf(stderr,"can not create XACML Action/Attribute:%s\n",XACML_ACTION_ID);
        xacml_subject_delete(subject);
        xacml_resource_delete(resource);
        xacml_action_delete(action);
        return 3;
    }
    xacml_attribute_addvalue(action_attr_id,actionid);
    xacml_action_addattribute(action,action_attr_id);

    /* XACML Request with all elements */
    *request= xacml_request_create();
    if (*request == NULL) {
        fprintf(stderr,"can not create XACML Request\n");
        xacml_subject_delete(subject);
        xacml_resource_delete(resource);
        xacml_action_delete(action);
        return 4;
    }
    xacml_request_addsubject(*request,subject);
    xacml_request_addresource(*request,resource);
    xacml_request_setaction(*request,action);
    
    return 0;
}

/*
 * Simply dump the XACML response.
 *
 * @param [in] response the XAXML response
 * @return 0 on success or error code on failure. 
 */
static int process_xacml_response(const xacml_response_t * response) {
    size_t results_l;
    int i, j, k;
    if (response == NULL) {
        fprintf(stderr,"response is NULL\n");
        return 1;
    }
    results_l= xacml_response_results_length(response);
    fprintf(stdout,"response: %d results\n", (int)results_l);
    for(i= 0; i<results_l; i++) {
        xacml_result_t * result;
        xacml_status_t * status;
        xacml_statuscode_t * statuscode, * subcode;
        size_t obligations_l;
        
        result= xacml_response_getresult(response,i);
        fprintf(stdout,"response.result[%d].decision= %s\n", i, decision_tostring(xacml_result_getdecision(result)));
        fprintf(stdout,"response.result[%d].resourceid= %s\n", i, xacml_result_getresourceid(result));
        
        status= xacml_result_getstatus(result);
        fprintf(stdout,"response.result[%d].status.message= %s\n", i, xacml_status_getmessage(status));
        statuscode= xacml_status_getcode(status);
        fprintf(stdout,"response.result[%d].status.code.value= %s\n", i, xacml_statuscode_getvalue(statuscode));
        subcode= xacml_statuscode_getsubcode(statuscode);
        if (subcode != NULL) {
            fprintf(stdout,"response.result[%d].status.code.subcode.value= %s\n", i, xacml_statuscode_getvalue(subcode));
        }
        obligations_l= xacml_result_obligations_length(result);
        fprintf(stdout,"response.result[%d]: %d obligations\n", i, (int)obligations_l);
        for(j= 0; j<obligations_l; j++) {
            size_t attrs_l;
            xacml_obligation_t * obligation= xacml_result_getobligation(result,j);
            fprintf(stdout,"response.result[%d].obligation[%d].id= %s\n",i,j, xacml_obligation_getid(obligation));
            fprintf(stdout,"response.result[%d].obligation[%d].fulfillOn= %s\n",i,j, fulfillon_tostring(xacml_obligation_getfulfillon(obligation)));
            attrs_l= xacml_obligation_attributeassignments_length(obligation);
            fprintf(stdout,"response.result[%d].obligation[%d]: %d attribute assignments\n",i,j,(int)attrs_l);
            for (k= 0; k<attrs_l; k++) {
                xacml_attributeassignment_t * attr= xacml_obligation_getattributeassignment(obligation,k);
                fprintf(stdout,"response.result[%d].obligation[%d].attributeassignment[%d].id= %s\n",i,j,k,xacml_attributeassignment_getid(attr));
                fprintf(stdout,"response.result[%d].obligation[%d].attributeassignment[%d].datatype= %s\n",i,j,k,xacml_attributeassignment_getdatatype(attr));
                fprintf(stdout,"response.result[%d].obligation[%d].attributeassignment[%d].value= %s\n",i,j,k,xacml_attributeassignment_getvalue(attr));
            }
        }
    }
    return 0;
}

/*
 * Returns the string representation of the decision.
 */
static const char * decision_tostring(xacml_decision_t decision) {
    switch(decision) {
    case XACML_DECISION_DENY:
        return "Deny";
        break;
    case XACML_DECISION_PERMIT:
        return "Permit";
        break;
    case XACML_DECISION_INDETERMINATE:
        return "Indeterminate";
        break;
    case XACML_DECISION_NOT_APPLICABLE:
        return "Not Applicable";
        break;
    default:
        return "ERROR (Unknown Decision)";
        break;
    }
}

/*
 * Returns the string representation of the fulfillOn.
 */
static const char * fulfillon_tostring(xacml_fulfillon_t fulfillon) {
    switch(fulfillon) {
    case XACML_FULFILLON_DENY:
        return "Deny";
        break;
    case XACML_FULFILLON_PERMIT:
        return "Permit";
        break;
    default:
        return "ERROR (Unknown FulfillOn)";
        break;
    }
}

Generated on 29 Apr 2014 for Argus PEP client API by  doxygen 1.6.1