mirror of
https://github.com/strongswan/strongswan.git
synced 2025-10-06 00:00:47 -04:00
libimcv: Support symlinks introduced by usrmerge
Debian, Ubuntu, Fedora et. al. started to apply usrmerge to their latest Linux distributions, i.e. /bin, /sbin, and /lib are now symbolical links to /usr/bin, /usr/sbin, and /usr/lib, respectively. Since executables and libraries are contained only once in Linux packages (e.g. /bin/cp in coreutils but not /usr/bin/cp) this leads to missing file measurments due to the symlinks when doing remote attestation. The new ita_attr_symlinks PA-TNC attribute fixes this problem by collecting symbolic links pointing to directories on the client platform.
This commit is contained in:
parent
9b4a2322d6
commit
2ea1dac203
@ -42,6 +42,7 @@ libimcv_la_SOURCES := \
|
||||
ita/ita_attr_get_settings.h ita/ita_attr_get_settings.c \
|
||||
ita/ita_attr_settings.h ita/ita_attr_settings.c \
|
||||
ita/ita_attr_angel.h ita/ita_attr_angel.c \
|
||||
ita/ita_attr_symlinks.h ita/ita_attr_symlinks.c \
|
||||
os_info/os_info.h os_info/os_info.c \
|
||||
pa_tnc/pa_tnc_attr.h \
|
||||
pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
|
||||
@ -60,6 +61,7 @@ libimcv_la_SOURCES := \
|
||||
pts/pts_ima_bios_list.h pts/pts_ima_bios_list.c \
|
||||
pts/pts_ima_event_list.h pts/pts_ima_event_list.c \
|
||||
pts/pts_meas_algo.h pts/pts_meas_algo.c \
|
||||
pts/pts_symlinks.h pts/pts_symlinks.c \
|
||||
pts/components/pts_component.h \
|
||||
pts/components/pts_component_manager.h pts/components/pts_component_manager.c \
|
||||
pts/components/pts_comp_evidence.h pts/components/pts_comp_evidence.c \
|
||||
|
@ -63,6 +63,7 @@ libimcv_la_SOURCES = \
|
||||
ita/ita_attr_get_settings.h ita/ita_attr_get_settings.c \
|
||||
ita/ita_attr_settings.h ita/ita_attr_settings.c \
|
||||
ita/ita_attr_angel.h ita/ita_attr_angel.c \
|
||||
ita/ita_attr_symlinks.h ita/ita_attr_symlinks.c \
|
||||
os_info/os_info.h os_info/os_info.c \
|
||||
pa_tnc/pa_tnc_attr.h \
|
||||
pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
|
||||
@ -81,6 +82,7 @@ libimcv_la_SOURCES = \
|
||||
pts/pts_ima_bios_list.h pts/pts_ima_bios_list.c \
|
||||
pts/pts_ima_event_list.h pts/pts_ima_event_list.c \
|
||||
pts/pts_meas_algo.h pts/pts_meas_algo.c \
|
||||
pts/pts_symlinks.h pts/pts_symlinks.c \
|
||||
pts/components/pts_component.h \
|
||||
pts/components/pts_component_manager.h pts/components/pts_component_manager.c \
|
||||
pts/components/pts_comp_evidence.h pts/components/pts_comp_evidence.c \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* Copyright (C) 2011-2020 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@ -19,9 +19,10 @@
|
||||
#include "ita/ita_attr_get_settings.h"
|
||||
#include "ita/ita_attr_settings.h"
|
||||
#include "ita/ita_attr_angel.h"
|
||||
#include "ita/ita_attr_symlinks.h"
|
||||
#include "generic/generic_attr_string.h"
|
||||
|
||||
ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_DEVICE_ID,
|
||||
ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_SYMLINKS,
|
||||
"Command",
|
||||
"Dummy",
|
||||
"Get Settings",
|
||||
@ -29,7 +30,9 @@ ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_DEVICE_ID,
|
||||
"Start Angel",
|
||||
"Stop Angel",
|
||||
"Echo",
|
||||
"Device ID"
|
||||
"Device ID",
|
||||
"Get Symlinks",
|
||||
"Symlinks"
|
||||
);
|
||||
|
||||
/**
|
||||
@ -55,6 +58,11 @@ pa_tnc_attr_t* ita_attr_create_from_data(uint32_t type, size_t length,
|
||||
case ITA_ATTR_DEVICE_ID:
|
||||
return generic_attr_string_create_from_data(length, value,
|
||||
pen_type_create(PEN_ITA, type));
|
||||
case ITA_ATTR_GET_SYMLINKS:
|
||||
return generic_attr_string_create_from_data(length, value,
|
||||
pen_type_create(PEN_ITA, type));
|
||||
case ITA_ATTR_SYMLINKS:
|
||||
return ita_attr_symlinks_create_from_data(length, value);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* Copyright (C) 2011-2020 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@ -38,7 +38,9 @@ enum ita_attr_t {
|
||||
ITA_ATTR_START_ANGEL = 5,
|
||||
ITA_ATTR_STOP_ANGEL = 6,
|
||||
ITA_ATTR_ECHO = 7,
|
||||
ITA_ATTR_DEVICE_ID = 8
|
||||
ITA_ATTR_DEVICE_ID = 8,
|
||||
ITA_ATTR_GET_SYMLINKS = 9,
|
||||
ITA_ATTR_SYMLINKS = 10
|
||||
};
|
||||
|
||||
/**
|
||||
|
318
src/libimcv/ita/ita_attr_symlinks.c
Normal file
318
src/libimcv/ita/ita_attr_symlinks.c
Normal file
@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "ita_attr_symlinks.h"
|
||||
|
||||
#include <pa_tnc/pa_tnc_msg.h>
|
||||
#include <bio/bio_writer.h>
|
||||
#include <bio/bio_reader.h>
|
||||
#include <collections/linked_list.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_ita_attr_symlinks_t private_ita_attr_symlinks_t;
|
||||
|
||||
/**
|
||||
* List of Symbolic Links pointing to Directories
|
||||
*
|
||||
* 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Number of Symlinks |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Symlink #1 Length | Symlink #1 Path (Var Len) ~
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Symlink #1 Path (Variable Length) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Directory #1 Length | Directory #1 Path (Var Len) ~
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Directory #1 Path (Variable Length) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Symlink #2 Length | Symlink #2 Path (Var Len) ~
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Symlink #2 Path (Variable Length) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Directory #2 Length | Directory #2 Path (Var Len) ~
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Directory #2 Path (Variable Length) |
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* ...........................
|
||||
*/
|
||||
|
||||
#define ITA_ATTR_SYMLINKS_SIZE 4
|
||||
|
||||
/**
|
||||
* Private data of an ita_attr_symlinks_t object.
|
||||
*/
|
||||
struct private_ita_attr_symlinks_t {
|
||||
|
||||
/**
|
||||
* Public members of ita_attr_symlinks_t
|
||||
*/
|
||||
ita_attr_symlinks_t public;
|
||||
|
||||
/**
|
||||
* Vendor-specific attribute type
|
||||
*/
|
||||
pen_type_t type;
|
||||
|
||||
/**
|
||||
* Length of attribute value
|
||||
*/
|
||||
size_t length;
|
||||
|
||||
/**
|
||||
* Offset up to which attribute value has been processed
|
||||
*/
|
||||
size_t offset;
|
||||
|
||||
/**
|
||||
* Current position of attribute value pointer
|
||||
*/
|
||||
chunk_t value;
|
||||
|
||||
/**
|
||||
* Contains complete attribute or current segment
|
||||
*/
|
||||
chunk_t segment;
|
||||
|
||||
/**
|
||||
* Noskip flag
|
||||
*/
|
||||
bool noskip_flag;
|
||||
|
||||
/**
|
||||
* Number of symbolic link entries
|
||||
*/
|
||||
uint32_t count;
|
||||
|
||||
/**
|
||||
* List of symbolic links
|
||||
*/
|
||||
pts_symlinks_t *symlinks;
|
||||
|
||||
/**
|
||||
* Reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
};
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_type, pen_type_t,
|
||||
private_ita_attr_symlinks_t *this)
|
||||
{
|
||||
return this->type;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_value, chunk_t,
|
||||
private_ita_attr_symlinks_t *this)
|
||||
{
|
||||
return this->value;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
|
||||
private_ita_attr_symlinks_t *this)
|
||||
{
|
||||
return this->noskip_flag;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, set_noskip_flag,void,
|
||||
private_ita_attr_symlinks_t *this, bool noskip)
|
||||
{
|
||||
this->noskip_flag = noskip;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, build, void,
|
||||
private_ita_attr_symlinks_t *this)
|
||||
{
|
||||
bio_writer_t *writer;
|
||||
enumerator_t *enumerator;
|
||||
chunk_t symlink, dir;
|
||||
|
||||
if (this->value.ptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this->count = this->symlinks->get_count(this->symlinks);
|
||||
|
||||
writer = bio_writer_create(ITA_ATTR_SYMLINKS_SIZE);
|
||||
writer->write_uint32(writer, this->count);
|
||||
|
||||
enumerator = this->symlinks->create_enumerator(this->symlinks);
|
||||
while (enumerator->enumerate(enumerator, &symlink, &dir))
|
||||
{
|
||||
writer->write_data16(writer, symlink);
|
||||
writer->write_data16(writer, dir);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
this->value = writer->extract_buf(writer);
|
||||
this->segment = this->value;
|
||||
this->length = this->value.len;
|
||||
writer->destroy(writer);
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, process, status_t,
|
||||
private_ita_attr_symlinks_t *this, uint32_t *offset)
|
||||
{
|
||||
bio_reader_t *reader;
|
||||
chunk_t symlink, dir;
|
||||
status_t status = NEED_MORE;
|
||||
|
||||
if (this->offset == 0)
|
||||
{
|
||||
if (this->length < ITA_ATTR_SYMLINKS_SIZE)
|
||||
{
|
||||
DBG1(DBG_TNC, "insufficient data for %N/%N", pen_names, PEN_ITA,
|
||||
ita_attr_names, this->type.type);
|
||||
*offset = this->offset;
|
||||
return FAILED;
|
||||
}
|
||||
if (this->value.len < ITA_ATTR_SYMLINKS_SIZE)
|
||||
{
|
||||
return NEED_MORE;
|
||||
}
|
||||
reader = bio_reader_create(this->value);
|
||||
reader->read_uint32(reader, &this->count);
|
||||
this->offset = ITA_ATTR_SYMLINKS_SIZE;
|
||||
this->value = reader->peek(reader);
|
||||
reader->destroy(reader);
|
||||
}
|
||||
|
||||
this->symlinks = pts_symlinks_create();
|
||||
reader = bio_reader_create(this->value);
|
||||
|
||||
while (this->count)
|
||||
{
|
||||
if (!reader->read_data16(reader, &symlink) ||
|
||||
!reader->read_data16(reader, &dir))
|
||||
{
|
||||
goto end;
|
||||
}
|
||||
this->offset += this->value.len - reader->remaining(reader);
|
||||
this->value = reader->peek(reader);
|
||||
this->symlinks->add(this->symlinks, symlink, dir);
|
||||
this->count--;
|
||||
}
|
||||
|
||||
status = SUCCESS;
|
||||
|
||||
if (this->length != this->offset)
|
||||
{
|
||||
DBG1(DBG_TNC, "inconsistent length for %N/%N", pen_names, PEN_ITA,
|
||||
ita_attr_names, this->type.type);
|
||||
*offset = this->offset;
|
||||
status = FAILED;
|
||||
}
|
||||
|
||||
end:
|
||||
reader->destroy(reader);
|
||||
return status;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, add_segment, void,
|
||||
private_ita_attr_symlinks_t *this, chunk_t segment)
|
||||
{
|
||||
this->value = chunk_cat("cc", this->value, segment);
|
||||
chunk_free(&this->segment);
|
||||
this->segment = this->value;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
|
||||
private_ita_attr_symlinks_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public.pa_tnc_attribute;
|
||||
}
|
||||
|
||||
METHOD(pa_tnc_attr_t, destroy, void,
|
||||
private_ita_attr_symlinks_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
DESTROY_IF(this->symlinks);
|
||||
free(this->segment.ptr);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(ita_attr_symlinks_t, get_symlinks, pts_symlinks_t*,
|
||||
private_ita_attr_symlinks_t *this)
|
||||
{
|
||||
return this->symlinks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t *ita_attr_symlinks_create(pts_symlinks_t *symlinks)
|
||||
{
|
||||
private_ita_attr_symlinks_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.pa_tnc_attribute = {
|
||||
.get_type = _get_type,
|
||||
.get_value = _get_value,
|
||||
.get_noskip_flag = _get_noskip_flag,
|
||||
.set_noskip_flag = _set_noskip_flag,
|
||||
.build = _build,
|
||||
.process = _process,
|
||||
.add_segment = _add_segment,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.get_symlinks = _get_symlinks,
|
||||
},
|
||||
.type = { PEN_ITA, ITA_ATTR_SYMLINKS },
|
||||
.symlinks = symlinks->get_ref(symlinks),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return &this->public.pa_tnc_attribute;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Described in header.
|
||||
*/
|
||||
pa_tnc_attr_t *ita_attr_symlinks_create_from_data(size_t length, chunk_t data)
|
||||
{
|
||||
private_ita_attr_symlinks_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.pa_tnc_attribute = {
|
||||
.get_type = _get_type,
|
||||
.get_value = _get_value,
|
||||
.get_noskip_flag = _get_noskip_flag,
|
||||
.set_noskip_flag = _set_noskip_flag,
|
||||
.build = _build,
|
||||
.process = _process,
|
||||
.add_segment = _add_segment,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.get_symlinks = _get_symlinks,
|
||||
},
|
||||
.type = { PEN_ITA, ITA_ATTR_SYMLINKS },
|
||||
.length = length,
|
||||
.segment = chunk_clone(data),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
/* received either complete attribute value or first segment */
|
||||
this->value = this->segment;
|
||||
|
||||
return &this->public.pa_tnc_attribute;
|
||||
}
|
63
src/libimcv/ita/ita_attr_symlinks.h
Normal file
63
src/libimcv/ita/ita_attr_symlinks.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup ita_attr_sysmlinks ita_attr_sysmlinks
|
||||
* @{ @ingroup ita_attr
|
||||
*/
|
||||
|
||||
#ifndef ITA_ATTR_SYMLINKS_H_
|
||||
#define ITA_ATTR_SYMLINKS_H_
|
||||
|
||||
typedef struct ita_attr_symlinks_t ita_attr_symlinks_t;
|
||||
|
||||
#include "ita/ita_attr.h"
|
||||
#include "pa_tnc/pa_tnc_attr.h"
|
||||
#include "pts/pts_symlinks.h"
|
||||
|
||||
/**
|
||||
* Class implementing the ITA Symlinks attribute
|
||||
*
|
||||
*/
|
||||
struct ita_attr_symlinks_t {
|
||||
|
||||
/**
|
||||
* Public PA-TNC attribute interface
|
||||
*/
|
||||
pa_tnc_attr_t pa_tnc_attribute;
|
||||
|
||||
/**
|
||||
* Get list of symbolic links
|
||||
*
|
||||
* @return List of symbolic links pointing to directories
|
||||
*/
|
||||
pts_symlinks_t* (*get_symlinks)(ita_attr_symlinks_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an ita_attr_sysmlinks_t object
|
||||
*/
|
||||
pa_tnc_attr_t* ita_attr_symlinks_create(pts_symlinks_t *symlinks);
|
||||
|
||||
/**
|
||||
* Creates an ita_attr_sysmlinks_t object from received data
|
||||
*
|
||||
* @param length Total length of attribute value
|
||||
* @param value Unparsed attribute value (might be a segment)
|
||||
*/
|
||||
pa_tnc_attr_t* ita_attr_symlinks_create_from_data(size_t length, chunk_t value);
|
||||
|
||||
#endif /** ITA_ATTR_SYMLINKS_H_ @}*/
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* Copyright (C) 2011-2020 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@ -24,6 +24,7 @@
|
||||
#include <ietf/ietf_attr_product_info.h>
|
||||
#include <ietf/ietf_attr_string_version.h>
|
||||
#include <ietf/ietf_attr_assess_result.h>
|
||||
#include <ita/ita_attr_symlinks.h>
|
||||
#include <tcg/pts/tcg_pts_attr_proto_caps.h>
|
||||
#include <tcg/pts/tcg_pts_attr_meas_algo.h>
|
||||
#include <os_info/os_info.h>
|
||||
@ -200,6 +201,25 @@ static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (type.vendor_id == PEN_ITA)
|
||||
{
|
||||
if (type.type == ITA_ATTR_GET_SYMLINKS)
|
||||
{
|
||||
pts_symlinks_t *symlinks;
|
||||
chunk_t dir;
|
||||
pts_t *pts;
|
||||
|
||||
dir = attr->get_value(attr);
|
||||
attestation_state = (imc_attestation_state_t*)state;
|
||||
pts = attestation_state->get_pts(attestation_state);
|
||||
symlinks = pts->extract_symlinks(pts, dir);
|
||||
if (symlinks)
|
||||
{
|
||||
attr = ita_attr_symlinks_create(symlinks);
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu
|
||||
* Copyright (C) 2011-2015 Andreas Steffen
|
||||
* Copyright (C) 2011-2020 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@ -34,6 +34,7 @@
|
||||
#include <ietf/ietf_attr_product_info.h>
|
||||
#include <ietf/ietf_attr_string_version.h>
|
||||
#include <ita/ita_attr.h>
|
||||
#include <ita/ita_attr_symlinks.h>
|
||||
#include <tcg/tcg_attr.h>
|
||||
#include <tcg/pts/tcg_pts_attr_meas_algo.h>
|
||||
#include <tcg/pts/tcg_pts_attr_proto_caps.h>
|
||||
@ -44,6 +45,7 @@
|
||||
#include <pts/pts.h>
|
||||
#include <pts/pts_database.h>
|
||||
#include <pts/pts_creds.h>
|
||||
#include <pts/pts_symlinks.h>
|
||||
#include <pts/components/ita/ita_comp_func_name.h>
|
||||
|
||||
#include <tncif_pa_subtypes.h>
|
||||
@ -287,6 +289,20 @@ static TNC_Result receive_msg(private_imv_attestation_agent_t *this,
|
||||
session->set_device_id(session, value);
|
||||
break;
|
||||
}
|
||||
case ITA_ATTR_SYMLINKS:
|
||||
{
|
||||
imv_attestation_state_t *attestation_state;
|
||||
ita_attr_symlinks_t *attr_cast;
|
||||
pts_symlinks_t *symlinks;
|
||||
pts_t *pts;
|
||||
|
||||
attr_cast = (ita_attr_symlinks_t*)attr;
|
||||
symlinks = attr_cast->get_symlinks(attr_cast);
|
||||
attestation_state = (imv_attestation_state_t*)state;
|
||||
pts = attestation_state->get_pts(attestation_state);
|
||||
pts->set_symlinks(pts, symlinks);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (C) 2011-2012 Sansar Choinyambuu
|
||||
* Copyright (C) 2011-2014 Andreas Steffen
|
||||
* Copyright (C) 2011-2020 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
@ -23,6 +23,8 @@
|
||||
#include <tcg/pts/tcg_pts_attr_get_aik.h>
|
||||
#include <tcg/pts/tcg_pts_attr_req_func_comp_evid.h>
|
||||
#include <tcg/pts/tcg_pts_attr_gen_attest_evid.h>
|
||||
#include <generic/generic_attr_string.h>
|
||||
#include <ita/ita_attr.h>
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
@ -138,6 +140,11 @@ bool imv_attestation_build(imv_msg_t *out_msg, imv_state_t *state,
|
||||
|
||||
if (attr)
|
||||
{
|
||||
/* Send Get Symlinks attribute */
|
||||
out_msg->add_attribute(out_msg, generic_attr_string_create(
|
||||
chunk_from_str("/"),
|
||||
pen_type_create(PEN_ITA, ITA_ATTR_GET_SYMLINKS)));
|
||||
|
||||
/* Send Request Functional Component Evidence attribute */
|
||||
out_msg->add_attribute(out_msg, attr);
|
||||
|
||||
|
@ -13,6 +13,9 @@
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
|
||||
#include "ita_comp_ima.h"
|
||||
#include "ita_comp_func_name.h"
|
||||
|
||||
@ -497,6 +500,123 @@ static pts_meas_algorithms_t parse_validation_uri(pts_comp_evidence_t *evidence,
|
||||
return hash_algo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up all hashes for a given file and OS in the database and check
|
||||
* if one of them matches the IMA measurement
|
||||
*/
|
||||
static status_t verify_ima_measuremnt(pts_t *pts, pts_database_t *pts_db,
|
||||
pts_meas_algorithms_t hash_algo,
|
||||
pts_meas_algorithms_t algo,
|
||||
bool pcr_padding, chunk_t measurement,
|
||||
char* ima_algo, char* ima_name,
|
||||
char *filename)
|
||||
{
|
||||
status_t status = NOT_FOUND;
|
||||
pts_meas_algorithms_t meas_algo;
|
||||
uint8_t *hex_digest_buf;
|
||||
uint8_t digest_buf[HASH_SIZE_SHA512];
|
||||
uint8_t hash_buf[HASH_SIZE_SHA512];
|
||||
size_t hash_size;
|
||||
chunk_t hash, digest, hex_digest;
|
||||
enumerator_t *e;
|
||||
|
||||
hash_size = pts_meas_algo_hash_size(algo);
|
||||
hash = chunk_create(hash_buf, hash_size);
|
||||
|
||||
if (pcr_padding)
|
||||
{
|
||||
memset(hash_buf, 0x00, hash_size);
|
||||
meas_algo = PTS_MEAS_ALGO_SHA1;
|
||||
}
|
||||
else
|
||||
{
|
||||
meas_algo = algo;
|
||||
}
|
||||
|
||||
e = pts_db->create_file_meas_enumerator(pts_db, pts->get_platform_id(pts),
|
||||
hash_algo, filename);
|
||||
if (!e)
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
while (e->enumerate(e, &hex_digest_buf))
|
||||
{
|
||||
hex_digest = chunk_from_str(hex_digest_buf);
|
||||
digest = chunk_from_hex(hex_digest, digest_buf);
|
||||
|
||||
if (!pts_ima_event_hash(digest, ima_algo, ima_name, meas_algo, hash_buf))
|
||||
{
|
||||
status = FAILED;
|
||||
break;
|
||||
}
|
||||
if (chunk_equals_const(measurement, hash))
|
||||
{
|
||||
status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = VERIFY_ERROR;
|
||||
}
|
||||
}
|
||||
e->destroy(e);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an alternative pathname based on symbolic link info
|
||||
*/
|
||||
static char* alternative_pathname(pts_t * pts, char *path)
|
||||
{
|
||||
pts_symlinks_t *symlinks;
|
||||
enumerator_t *enumerator;
|
||||
chunk_t prefix1, prefix2;
|
||||
char *alt_path = NULL;
|
||||
size_t path_len = strlen(path);
|
||||
int ret;
|
||||
|
||||
symlinks = pts->get_symlinks(pts);
|
||||
if (!symlinks || symlinks->get_count(symlinks) == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enumerator = symlinks->create_enumerator(symlinks);
|
||||
while (enumerator->enumerate(enumerator, &prefix1, &prefix2))
|
||||
{
|
||||
/* replace prefix2 by prefix1*/
|
||||
if (path_len > prefix2.len && path[prefix2.len] == '/' &&
|
||||
memeq(path, prefix2.ptr, prefix2.len))
|
||||
{
|
||||
ret = asprintf(&alt_path, "%.*s%s", (int)prefix1.len, prefix1.ptr,
|
||||
path + prefix2.len);
|
||||
if (ret <= 0)
|
||||
{
|
||||
alt_path = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* replace prefix1 by prefix2 */
|
||||
if (path_len > prefix1.len && path[prefix1.len] == '/' &&
|
||||
memeq(path, prefix1.ptr, prefix1.len))
|
||||
{
|
||||
ret = asprintf(&alt_path, "%.*s%s", (int)prefix2.len, prefix2.ptr,
|
||||
path + prefix1.len);
|
||||
if (ret <= 0)
|
||||
{
|
||||
alt_path = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
|
||||
return alt_path;
|
||||
}
|
||||
|
||||
METHOD(pts_component_t, verify, status_t,
|
||||
pts_ita_comp_ima_t *this, uint8_t qualifier, pts_t *pts,
|
||||
pts_comp_evidence_t *evidence)
|
||||
@ -665,14 +785,8 @@ METHOD(pts_component_t, verify, status_t,
|
||||
break;
|
||||
case IMA_STATE_RUNTIME:
|
||||
{
|
||||
chunk_t hex_digest, digest, hash;
|
||||
uint8_t digest_buf[HASH_SIZE_SHA512], *hex_digest_buf;
|
||||
uint8_t hash_buf[HASH_SIZE_SHA512];
|
||||
size_t hash_size;
|
||||
pts_meas_algorithms_t meas_algo;
|
||||
enumerator_t *e;
|
||||
|
||||
this->count++;
|
||||
|
||||
if (evidence->get_validation(evidence, NULL) !=
|
||||
PTS_COMP_EVID_VALIDATION_PASSED)
|
||||
{
|
||||
@ -680,50 +794,30 @@ METHOD(pts_component_t, verify, status_t,
|
||||
this->count_failed++;
|
||||
return FAILED;
|
||||
}
|
||||
hash_size = pts_meas_algo_hash_size(algo);
|
||||
hash = chunk_create(hash_buf, hash_size);
|
||||
|
||||
if (this->pcr_padding)
|
||||
{
|
||||
memset(hash_buf, 0x00, hash_size);
|
||||
meas_algo = PTS_MEAS_ALGO_SHA1;
|
||||
}
|
||||
else
|
||||
{
|
||||
meas_algo = algo;
|
||||
}
|
||||
status = verify_ima_measuremnt(pts, this->pts_db,
|
||||
hash_algo, algo,
|
||||
this->pcr_padding, measurement,
|
||||
ima_algo, ima_name, ima_name);
|
||||
|
||||
e = this->pts_db->create_file_meas_enumerator(this->pts_db,
|
||||
pts->get_platform_id(pts),
|
||||
hash_algo, ima_name);
|
||||
if (e)
|
||||
if (status == NOT_FOUND || status == VERIFY_ERROR)
|
||||
{
|
||||
while (e->enumerate(e, &hex_digest_buf))
|
||||
status_t alt_status;
|
||||
char *alt_path;
|
||||
|
||||
alt_path = alternative_pathname(pts, ima_name);
|
||||
if (alt_path)
|
||||
{
|
||||
hex_digest = chunk_from_str(hex_digest_buf);
|
||||
digest = chunk_from_hex(hex_digest, digest_buf);
|
||||
|
||||
if (!pts_ima_event_hash(digest, ima_algo, ima_name,
|
||||
meas_algo, hash_buf))
|
||||
alt_status = verify_ima_measuremnt(pts, this->pts_db,
|
||||
hash_algo, algo,
|
||||
this->pcr_padding, measurement,
|
||||
ima_algo, ima_name, alt_path);
|
||||
if (alt_status != NOT_FOUND)
|
||||
{
|
||||
status = FAILED;
|
||||
break;
|
||||
}
|
||||
if (chunk_equals_const(measurement, hash))
|
||||
{
|
||||
status = SUCCESS;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = VERIFY_ERROR;
|
||||
status = alt_status;
|
||||
}
|
||||
free(alt_path);
|
||||
}
|
||||
e->destroy(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = FAILED;
|
||||
}
|
||||
|
||||
switch (status)
|
||||
|
@ -27,8 +27,10 @@
|
||||
#include <sys/stat.h>
|
||||
#include <libgen.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#ifndef TPM_TAG_QUOTE_INFO2
|
||||
#define TPM_TAG_QUOTE_INFO2 0x0036
|
||||
#endif
|
||||
@ -89,6 +91,11 @@ struct private_pts_t {
|
||||
*/
|
||||
int platform_id;
|
||||
|
||||
/**
|
||||
* List of directory symlinks received from IMC
|
||||
*/
|
||||
pts_symlinks_t *symlinks;
|
||||
|
||||
/**
|
||||
* TRUE if IMC-PTS, FALSE if IMV-PTS
|
||||
*/
|
||||
@ -309,6 +316,104 @@ METHOD(pts_t, set_platform_id, void,
|
||||
this->platform_id = pid;
|
||||
}
|
||||
|
||||
METHOD(pts_t, extract_symlinks, pts_symlinks_t*,
|
||||
private_pts_t *this, chunk_t pathname)
|
||||
{
|
||||
#ifndef WIN32
|
||||
char path[BUF_LEN], real_path[BUF_LEN];
|
||||
size_t path_len, real_path_len;
|
||||
struct dirent *entry;
|
||||
struct stat st;
|
||||
DIR *dir;
|
||||
|
||||
/* open directory and prepare pathnames */
|
||||
snprintf(path, BUF_LEN-1, "%.*s", (int)pathname.len, pathname.ptr);
|
||||
dir = opendir(path);
|
||||
if (!dir)
|
||||
{
|
||||
DBG1(DBG_PTS, "opening directory '%s' failed: %s", path,
|
||||
strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
if (pathname.len == 1 && path[0] == '/')
|
||||
{
|
||||
path_len = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
path[pathname.len] = '/';
|
||||
path_len = pathname.len + 1;
|
||||
}
|
||||
real_path[0] = '/';
|
||||
|
||||
/* symlinks object is owned by pts object */
|
||||
DESTROY_IF(this->symlinks);
|
||||
this->symlinks = pts_symlinks_create();
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
|
||||
entry = readdir(dir);
|
||||
if (!entry)
|
||||
{
|
||||
/* no more entries -> exit */
|
||||
break;
|
||||
}
|
||||
if (streq(entry->d_name, ".") || streq(entry->d_name, ".."))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* assemble absolute path */
|
||||
snprintf(path + path_len, BUF_LEN - path_len, "%s", entry->d_name);
|
||||
|
||||
/* only evaluate symlinks pointing to directories */
|
||||
if (lstat(path, &st) == -1 || !S_ISLNK(st.st_mode) ||
|
||||
stat(path, &st) == -1 || !S_ISDIR(st.st_mode))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
real_path_len = readlink(path, real_path + 1, BUF_LEN - 1);
|
||||
if (real_path_len <= 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
this->symlinks->add(this->symlinks, chunk_from_str(path),
|
||||
chunk_create(real_path, 1 + real_path_len));
|
||||
}
|
||||
closedir(dir);
|
||||
#endif
|
||||
|
||||
return this->symlinks;
|
||||
}
|
||||
|
||||
|
||||
METHOD(pts_t, get_symlinks, pts_symlinks_t*,
|
||||
private_pts_t *this)
|
||||
{
|
||||
return this->symlinks;
|
||||
}
|
||||
|
||||
METHOD(pts_t, set_symlinks, void,
|
||||
private_pts_t *this, pts_symlinks_t *symlinks)
|
||||
{
|
||||
enumerator_t *enumerator;
|
||||
chunk_t symlink, dir;
|
||||
|
||||
DESTROY_IF(this->symlinks);
|
||||
this->symlinks = symlinks->get_ref(symlinks);
|
||||
|
||||
DBG2(DBG_PTS, "adding directory symlinks:");
|
||||
enumerator = symlinks->create_enumerator(symlinks);
|
||||
while (enumerator->enumerate(enumerator, &symlink, &dir))
|
||||
{
|
||||
DBG2(DBG_PTS, " %.*s -> %.*s", (int)symlink.len, symlink.ptr,
|
||||
(int)dir.len, dir.ptr);
|
||||
}
|
||||
enumerator->destroy(enumerator);
|
||||
}
|
||||
|
||||
METHOD(pts_t, get_tpm, tpm_tss_t*,
|
||||
private_pts_t *this)
|
||||
{
|
||||
@ -354,7 +459,7 @@ METHOD(pts_t, set_tpm_version_info, void,
|
||||
{
|
||||
DBG2(DBG_PTS, "%s 1.2 rev. %u.%u.%u.%u %.*s", TPM_VERSION_INFO_LABEL,
|
||||
(uint32_t)major, (uint32_t)minor, (uint32_t)rev_major,
|
||||
(uint32_t)rev_minor, vendor.len, vendor.ptr);
|
||||
(uint32_t)rev_minor, (int)vendor.len, vendor.ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -377,7 +482,7 @@ METHOD(pts_t, set_tpm_version_info, void,
|
||||
{
|
||||
DBG2(DBG_PTS, "%s 2.0 rev. %4.2f %u %.*s - startup locality: %u",
|
||||
TPM_VERSION_INFO_LABEL, revision/100.0, year,
|
||||
vendor.len, vendor.ptr, (uint32_t)locality);
|
||||
(int)vendor.len, vendor.ptr, (uint32_t)locality);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -873,6 +978,7 @@ METHOD(pts_t, destroy, void,
|
||||
DESTROY_IF(this->pcrs);
|
||||
DESTROY_IF(this->aik_cert);
|
||||
DESTROY_IF(this->dh);
|
||||
DESTROY_IF(this->symlinks);
|
||||
free(this->initiator_nonce.ptr);
|
||||
free(this->responder_nonce.ptr);
|
||||
free(this->secret.ptr);
|
||||
@ -901,6 +1007,9 @@ pts_t *pts_create(bool is_imc)
|
||||
.calculate_secret = _calculate_secret,
|
||||
.get_platform_id = _get_platform_id,
|
||||
.set_platform_id = _set_platform_id,
|
||||
.extract_symlinks = _extract_symlinks,
|
||||
.get_symlinks = _get_symlinks,
|
||||
.set_symlinks = _set_symlinks,
|
||||
.get_tpm = _get_tpm,
|
||||
.get_tpm_version_info = _get_tpm_version_info,
|
||||
.set_tpm_version_info = _set_tpm_version_info,
|
||||
|
@ -32,6 +32,7 @@ typedef struct pts_t pts_t;
|
||||
#include "pts_dh_group.h"
|
||||
#include "pts_pcr.h"
|
||||
#include "pts_req_func_comp_evid.h"
|
||||
#include "pts_symlinks.h"
|
||||
#include "components/pts_comp_func_name.h"
|
||||
|
||||
#include <tpm_tss_quote_info.h>
|
||||
@ -175,6 +176,29 @@ struct pts_t {
|
||||
*/
|
||||
void (*set_platform_id)(pts_t *this, int pid);
|
||||
|
||||
/**
|
||||
* Extract all directory symlinks contained in a directory
|
||||
*
|
||||
* @param pathname Absolute pathname of directory
|
||||
* @return List of directory symlinks
|
||||
*/
|
||||
pts_symlinks_t* (*extract_symlinks)(pts_t *this, chunk_t pathname);
|
||||
|
||||
/**
|
||||
* Get list of directory symlinks received from IMC
|
||||
*
|
||||
* @return List of symbolic links
|
||||
*/
|
||||
pts_symlinks_t* (*get_symlinks)(pts_t *this);
|
||||
|
||||
/**
|
||||
* Set list of directory symlinks received from IMC
|
||||
*
|
||||
* @param symlinks List of symbolic links
|
||||
*/
|
||||
void (*set_symlinks)(pts_t *this, pts_symlinks_t *symlinks);
|
||||
|
||||
|
||||
/**
|
||||
* Get TPM object handle
|
||||
*
|
||||
|
149
src/libimcv/pts/pts_symlinks.c
Normal file
149
src/libimcv/pts/pts_symlinks.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
#include "pts_symlinks.h"
|
||||
|
||||
#include <collections/linked_list.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
typedef struct private_pts_symlinks_t private_pts_symlinks_t;
|
||||
typedef struct entry_t entry_t;
|
||||
|
||||
/**
|
||||
* Private data of a pts_symlinks_t object.
|
||||
*
|
||||
*/
|
||||
struct private_pts_symlinks_t {
|
||||
|
||||
/**
|
||||
* Public pts_symlinks_t interface.
|
||||
*/
|
||||
pts_symlinks_t public;
|
||||
|
||||
/**
|
||||
* List of symbolic links pointing to directories
|
||||
*/
|
||||
linked_list_t *list;
|
||||
|
||||
/**
|
||||
* Reference count
|
||||
*/
|
||||
refcount_t ref;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Symlink entry
|
||||
*/
|
||||
struct entry_t {
|
||||
chunk_t symlink;
|
||||
chunk_t dir;
|
||||
};
|
||||
|
||||
/**
|
||||
* Free an entry_t object
|
||||
*/
|
||||
static void free_entry(entry_t *entry)
|
||||
{
|
||||
if (entry)
|
||||
{
|
||||
free(entry->symlink.ptr);
|
||||
free(entry->dir.ptr);
|
||||
free(entry);
|
||||
}
|
||||
}
|
||||
|
||||
METHOD(pts_symlinks_t, get_count, int,
|
||||
private_pts_symlinks_t *this)
|
||||
{
|
||||
return this->list->get_count(this->list);
|
||||
}
|
||||
|
||||
METHOD(pts_symlinks_t, add, void,
|
||||
private_pts_symlinks_t *this, chunk_t symlink, chunk_t dir)
|
||||
{
|
||||
entry_t *entry;
|
||||
|
||||
entry = malloc_thing(entry_t);
|
||||
entry->symlink = chunk_clone(symlink);
|
||||
entry->dir = chunk_clone(dir);
|
||||
|
||||
this->list->insert_last(this->list, entry);
|
||||
}
|
||||
|
||||
CALLBACK(symlink_filter, bool,
|
||||
void *null, enumerator_t *orig, va_list args)
|
||||
{
|
||||
entry_t *entry;
|
||||
chunk_t *symlink;
|
||||
chunk_t *dir;
|
||||
|
||||
VA_ARGS_VGET(args, symlink, dir);
|
||||
|
||||
if (orig->enumerate(orig, &entry))
|
||||
{
|
||||
*symlink = entry->symlink;
|
||||
*dir = entry->dir;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
METHOD(pts_symlinks_t, create_enumerator, enumerator_t*,
|
||||
private_pts_symlinks_t *this)
|
||||
{
|
||||
return enumerator_create_filter(this->list->create_enumerator(this->list),
|
||||
symlink_filter, NULL, NULL);
|
||||
}
|
||||
|
||||
METHOD(pts_symlinks_t, get_ref, pts_symlinks_t*,
|
||||
private_pts_symlinks_t *this)
|
||||
{
|
||||
ref_get(&this->ref);
|
||||
return &this->public;
|
||||
}
|
||||
|
||||
METHOD(pts_symlinks_t, destroy, void,
|
||||
private_pts_symlinks_t *this)
|
||||
{
|
||||
if (ref_put(&this->ref))
|
||||
{
|
||||
this->list->destroy_function(this->list, (void *)free_entry);
|
||||
free(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
pts_symlinks_t *pts_symlinks_create()
|
||||
{
|
||||
private_pts_symlinks_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.get_count = _get_count,
|
||||
.add = _add,
|
||||
.create_enumerator = _create_enumerator,
|
||||
.get_ref = _get_ref,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.list = linked_list_create(),
|
||||
.ref = 1,
|
||||
);
|
||||
|
||||
return &this->public;
|
||||
}
|
||||
|
76
src/libimcv/pts/pts_symlinks.h
Normal file
76
src/libimcv/pts/pts_symlinks.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Andreas Steffen
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup pts_symlinks pts_symlinks
|
||||
* @{ @ingroup pts
|
||||
*/
|
||||
|
||||
#ifndef PTS_SYMLINKS_H_
|
||||
#define PTS_SYMLINKS_H_
|
||||
|
||||
#include <library.h>
|
||||
|
||||
typedef struct pts_symlinks_t pts_symlinks_t;
|
||||
|
||||
|
||||
/**
|
||||
* Class storing a list of symbolic links pointing to directories
|
||||
*/
|
||||
struct pts_symlinks_t {
|
||||
|
||||
/**
|
||||
* Get the number of symbolic link entries
|
||||
*
|
||||
* @return Number of symbolic links
|
||||
*/
|
||||
int (*get_count)(pts_symlinks_t *this);
|
||||
|
||||
/**
|
||||
* Add a symbolic link pointing to a directory
|
||||
*
|
||||
* @param symlink Pathname of symbolic link
|
||||
* @param dir Pathname of directory the symlink points to
|
||||
*/
|
||||
void (*add)(pts_symlinks_t *this, chunk_t symlink, chunk_t dir);
|
||||
|
||||
/**
|
||||
* Create a symlink enumerator
|
||||
*
|
||||
* @return Enumerator returning (chunk_t symlink, chunk_t dir)
|
||||
*/
|
||||
enumerator_t* (*create_enumerator)(pts_symlinks_t *this);
|
||||
|
||||
/**
|
||||
* Get a new reference to the list of symbolic links
|
||||
*
|
||||
* @return this, with an increased refcount
|
||||
*/
|
||||
pts_symlinks_t* (*get_ref)(pts_symlinks_t *this);
|
||||
|
||||
|
||||
/**
|
||||
* Destroys a pts_symlinks_t object.
|
||||
*/
|
||||
void (*destroy)(pts_symlinks_t *this);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a pts_symlinks_t object
|
||||
*/
|
||||
pts_symlinks_t* pts_symlinks_create();
|
||||
|
||||
#endif /** PTS_SYMLINKS_H_ @}*/
|
Loading…
x
Reference in New Issue
Block a user