diff options
460 files changed, 13809 insertions, 2756 deletions
diff --git a/Android.mk b/Android.mk index 0b8da5b8d..b17a3f633 100644 --- a/Android.mk +++ b/Android.mk @@ -17,7 +17,7 @@ include $(CLEAR_VARS) # this is the list of plugins that are built into libstrongswan and charon # also these plugins are loaded by default (if not changed in strongswan.conf) strongswan_CHARON_PLUGINS := android-log openssl fips-prf random nonce pubkey \ - pkcs1 pkcs8 pem xcbc hmac kernel-netlink socket-default android \ + pkcs1 pkcs8 pem xcbc hmac kernel-netlink socket-default android-dns \ stroke eap-identity eap-mschapv2 eap-md5 eap-gtc ifneq ($(strongswan_BUILD_SCEPCLIENT),) diff --git a/Doxyfile.in b/Doxyfile.in index 343f130b3..ac0a96c88 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -1,14 +1,14 @@ -# Doxyfile 1.5.6 +# Doxyfile 1.8.1.2 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project +# doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored +# All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" ") +# Values that contain spaces should be placed between quotes (" "). #--------------------------------------------------------------------------- # Project related configuration options @@ -22,8 +22,9 @@ DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or a sequence of words surrounded -# by quotes) that should identify the project. +# The PROJECT_NAME tag is a single word (or sequence of words) that should +# identify the project. Note that if you do not use Doxywizard you need +# to put quotes around the project name if it contains spaces. PROJECT_NAME = "@PACKAGE_NAME@" @@ -33,6 +34,19 @@ PROJECT_NAME = "@PACKAGE_NAME@" PROJECT_NUMBER = "@PACKAGE_VERSION@" +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer +# a quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is +# included in the documentation. The maximum height of the logo should not +# exceed 55 pixels and the maximum width should not exceed 200 pixels. +# Doxygen will copy the logo to the output directory. + +PROJECT_LOGO = + # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location @@ -54,11 +68,11 @@ CREATE_SUBDIRS = NO # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, -# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, -# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, -# and Ukrainian. +# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, +# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English +# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, +# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, +# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English @@ -126,7 +140,7 @@ STRIP_FROM_PATH = STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful is your file systems +# (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO @@ -181,6 +195,13 @@ TAB_SIZE = 4 ALIASES = +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding +# "class=itcl::class" will allow you to use the command class in the +# itcl::class meaning. + +TCL_SUBST = + # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list @@ -207,11 +228,32 @@ OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given extension. +# Doxygen has a built-in mapping, but you can override or extend it using this +# tag. The format is ext=language, where ext is a file extension, and language +# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, +# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions +# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all +# comments according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you +# can mix doxygen, HTML, and XML commands with Markdown formatting. +# Disable only in case of backward compatibilities issues. + +MARKDOWN_SUPPORT = YES + # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also make the inheritance and collaboration +# func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO @@ -229,7 +271,7 @@ SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) -# will make doxygen to replace the get and set methods by a property in the +# will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. @@ -251,6 +293,22 @@ DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and +# unions are shown inside the group in which they are included (e.g. using +# @ingroup) instead of on a separate page (for HTML and Man pages) or +# section (for LaTeX and RTF). + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and +# unions with only public data fields will be shown inline in the documentation +# of the scope in which they are defined (i.e. file, namespace, or group +# documentation), provided this scope is documented. If set to NO (the default), +# structs, classes, and unions are shown on a separate page (for HTML and Man +# pages) or section (for LaTeX and RTF). + +INLINE_SIMPLE_STRUCTS = NO + # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct @@ -261,6 +319,33 @@ SUBGROUPING = YES TYPEDEF_HIDES_STRUCT = YES +# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to +# determine which symbols to keep in memory and which to flush to disk. +# When the cache is full, less often used symbols will be written to disk. +# For small to medium size projects (<1000 input files) the default value is +# probably good enough. For larger projects a too small cache size can cause +# doxygen to be busy swapping symbols to and from disk most of the time +# causing a significant performance penalty. +# If the system has enough physical memory increasing the cache will improve the +# performance by keeping more symbols in memory. Note that the value works on +# a logarithmic scale so increasing the size by one will roughly double the +# memory usage. The cache size is given by this formula: +# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +SYMBOL_CACHE_SIZE = 0 + +# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be +# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given +# their name and scope. Since this can be an expensive process and often the +# same symbol appear multiple times in the code, doxygen keeps a cache of +# pre-resolved symbols. If the cache is too small doxygen will become slower. +# If the cache is too large, memory is wasted. The cache size is given by this +# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, +# corresponding to a cache size of 2^16 = 65536 symbols. + +LOOKUP_CACHE_SIZE = 0 + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- @@ -277,6 +362,10 @@ EXTRACT_ALL = NO EXTRACT_PRIVATE = NO +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. + +EXTRACT_PACKAGE = NO + # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. @@ -299,7 +388,7 @@ EXTRACT_LOCAL_METHODS = NO # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default -# anonymous namespace are hidden. +# anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO @@ -359,6 +448,12 @@ HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = NO +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen +# will list include files with double quotes in the documentation +# rather than with sharp brackets. + +FORCE_LOCAL_INCLUDES = NO + # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. @@ -378,6 +473,16 @@ SORT_MEMBER_DOCS = NO SORT_BRIEF_DOCS = NO +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen +# will sort the (brief and detailed) documentation of class members so that +# constructors and destructors are listed first. If set to NO (the default) +# the constructors will appear in the respective orders defined by +# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. +# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO +# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. + +SORT_MEMBERS_CTORS_1ST = NO + # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. @@ -394,6 +499,15 @@ SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to +# do proper type resolution of all parameters of a function it will reject a +# match between the prototype and the implementation of a member function even +# if there is only one candidate or it is obvious which candidate to choose +# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen +# will still accept a match between prototype and implementation in such cases. + +STRICT_PROTO_MATCHING = NO + # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. @@ -424,10 +538,10 @@ GENERATE_DEPRECATEDLIST= NO ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or define consists of for it to appear in +# the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and defines in the +# The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. @@ -439,20 +553,15 @@ MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = NO -# If the sources in your project are distributed over multiple directories -# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy -# in the documentation. The default is NO. - -SHOW_DIRECTORIES = YES - # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. -SHOW_FILES = NO +SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. This will remove the Namespaces entry from the Quick Index +# Namespaces page. +# This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES @@ -467,6 +576,25 @@ SHOW_NAMESPACES = YES FILE_VERSION_FILTER = +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. +# You can optionally specify a file name after the option, if omitted +# DoxygenLayout.xml will be used as the name of the layout file. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files +# containing the references data. This must be a list of .bib files. The +# .bib extension is automatically appended if omitted. Using this command +# requires the bibtex tool to be installed. See also +# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style +# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this +# feature you need bibtex and perl available in the search path. + +CITE_BIB_FILES = + #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- @@ -495,13 +623,13 @@ WARN_IF_UNDOCUMENTED = NO WARN_IF_DOC_ERROR = YES -# This WARN_NO_PARAMDOC option can be abled to get warnings for +# The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. -WARN_NO_PARAMDOC = NO +WARN_NO_PARAMDOC = YES # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text @@ -527,17 +655,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = @SRC_DIR@/src/libstrongswan \ - @SRC_DIR@/src/libhydra \ - @SRC_DIR@/src/libcharon \ - @SRC_DIR@/src/libipsec \ - @SRC_DIR@/src/libsimaka \ - @SRC_DIR@/src/libtls \ - @SRC_DIR@/src/libradius \ - @SRC_DIR@/src/libtnccs \ - @SRC_DIR@/src/libtncif \ - @SRC_DIR@/src/libfast \ - @SRC_DIR@/src/manager +INPUT = @SRC_DIR@/src/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -551,8 +669,9 @@ INPUT_ENCODING = UTF-8 # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx -# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 +# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh +# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py +# *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = *.h @@ -562,17 +681,19 @@ FILE_PATTERNS = *.h RECURSIVE = YES -# The EXCLUDE tag can be used to specify files and/or directories that should +# The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# Note that relative paths are relative to the directory from which doxygen is +# run. -EXCLUDE = +EXCLUDE = @SRC_DIR@/src/include -# The EXCLUDE_SYMLINKS tag can be used select whether or not files or -# directories that are symbolic links (a Unix filesystem feature) are excluded +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded # from the input. -EXCLUDE_SYMLINKS = NO +EXCLUDE_SYMLINKS = YES # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude @@ -621,17 +742,20 @@ IMAGE_PATH = # by executing (via popen()) the command <filter> <input-file>, where <filter> # is the value of the INPUT_FILTER tag, and <input-file> is the name of an # input file. Doxygen will then use the output that the filter program writes -# to standard output. If FILTER_PATTERNS is specified, this tag will be +# to standard output. +# If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. The filters are a list of the form: +# basis. +# Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. +# The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER -# is applied to all files. +# info on how filters are used. If FILTER_PATTERNS is empty or if +# non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = @@ -641,6 +765,14 @@ FILTER_PATTERNS = FILTER_SOURCE_FILES = NO +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) +# and it is also possible to disable source filtering for a specific pattern +# using *.ext= (so without naming a filter). This option only has effect when +# FILTER_SOURCE_FILES is enabled. + +FILTER_SOURCE_PATTERNS = + #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- @@ -650,7 +782,7 @@ FILTER_SOURCE_FILES = NO # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. -SOURCE_BROWSER = NO +SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. @@ -659,7 +791,7 @@ INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code -# fragments. Normal C and C++ comments will always remain visible. +# fragments. Normal C, C++ and Fortran comments will always remain visible. STRIP_CODE_COMMENTS = NO @@ -678,7 +810,8 @@ REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. Otherwise they will link to the documentstion. +# link to the source code. +# Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES @@ -742,7 +875,14 @@ HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a -# standard header. +# standard header. Note that when using a custom header you are responsible +# for the proper inclusion of any scripts and style sheets that doxygen +# needs, which is dependent on the configuration options used. +# It is advised to generate a default header using "doxygen -w html +# header.html footer.html stylesheet.css YourConfigFile" and then modify +# that header. Note that the header is subject to change so you typically +# have to redo this when upgrading to a newer version of doxygen or when +# changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = @@ -757,22 +897,66 @@ HTML_FOOTER = # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own -# stylesheet in the HTML output directory as well, or it will be erased! +# style sheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = -# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, -# files or namespaces will be aligned in HTML using tables. If set to -# NO a bullet list will be used. +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that +# the files will be copied as-is; there are no commands or markers available. -HTML_ALIGN_MEMBERS = YES +HTML_EXTRA_FILES = -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. +# Doxygen will adjust the colors in the style sheet and background images +# according to this color. Hue is specified as an angle on a colorwheel, +# see http://en.wikipedia.org/wiki/Hue for more information. +# For instance the value 0 represents red, 60 is yellow, 120 is green, +# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. +# The allowed range is 0 to 359. -GENERATE_HTMLHELP = NO +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of +# the colors in the HTML output. For a value of 0 the output will use +# grayscales only. A value of 255 will produce the most vivid colors. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to +# the luminance component of the colors in the HTML output. Values below +# 100 gradually make the output lighter, whereas values above 100 make +# the output darker. The value divided by 100 is the actual gamma applied, +# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, +# and 100 does not change the gamma. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting +# this to NO can help when comparing the output of multiple runs. + +HTML_TIMESTAMP = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. + +HTML_DYNAMIC_SECTIONS = YES + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of +# entries shown in the various tree structured indices initially; the user +# can expand and collapse entries dynamically later on. Doxygen will expand +# the tree to such a level that at most the specified number of entries are +# visible (unless a fully collapsed tree already exceeds this amount). +# So setting the number of entries 1 will produce a full collapsed tree by +# default. 0 is a special value representing an infinite number of entries +# and will result in a full expanded tree by default. + +HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 @@ -782,6 +966,8 @@ GENERATE_HTMLHELP = NO # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. +# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. GENERATE_DOCSET = NO @@ -799,13 +985,22 @@ DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project -# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML -# documentation will contain sections that can be hidden and shown after the -# page has loaded. For this to work a browser that supports -# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox -# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. -HTML_DYNAMIC_SECTIONS = NO +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You @@ -844,40 +1039,114 @@ BINARY_TOC = NO TOC_EXPAND = NO -# The DISABLE_INDEX tag can be used to turn on/off the condensed index at -# top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated +# that can be used as input for Qt's qhelpgenerator to generate a +# Qt Compressed Help (.qch) of the generated HTML documentation. -DISABLE_INDEX = NO +GENERATE_QHP = NO -# This tag can be used to set the number of enum values (range [1..20]) -# that doxygen will group on one line in the generated HTML documentation. +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can +# be used to specify the file name of the resulting .qch file. +# The path specified is relative to the HTML output folder. -ENUM_VALUES_PER_LINE = 1 +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#namespace + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating +# Qt Help Project output. For more information please see +# http://doc.trolltech.com/qthelpproject.html#virtual-folders + +QHP_VIRTUAL_FOLDER = doc + +# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to +# add. For more information please see +# http://doc.trolltech.com/qthelpproject.html#custom-filters + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see +# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters"> +# Qt Help Project / Custom Filters</a>. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's +# filter section matches. +# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes"> +# Qt Help Project / Filter Attributes</a>. + +QHP_SECT_FILTER_ATTRS = + +# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can +# be used to specify the location of Qt's qhelpgenerator. +# If non-empty doxygen will try to run qhelpgenerator on the generated +# .qhp file. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files +# will be generated, which together with the HTML files, form an Eclipse help +# plugin. To install this plugin and make it available under the help contents +# menu in Eclipse, the contents of the directory containing the HTML and XML +# files needs to be copied into the plugins directory of eclipse. The name of +# the directory within the plugins directory should be the same as +# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before +# the help appears. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have +# this name. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) +# at top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. Since the tabs have the same information as the +# navigation tree you can set this option to NO if you already set +# GENERATE_TREEVIEW to YES. + +DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. -# If the tag value is set to FRAME, a side panel will be generated +# If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, -# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are -# probably better off using the HTML help feature. Other possible values -# for this tag are: HIERARCHIES, which will generate the Groups, Directories, -# and Class Hiererachy pages using a tree view instead of an ordered list; -# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which -# disables this behavior completely. For backwards compatibility with previous -# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE -# respectively. +# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). +# Windows users are probably better off using the HTML help feature. +# Since the tree basically has the same information as the tab index you +# could consider to set DISABLE_INDEX to NO when enabling this option. GENERATE_TREEVIEW = YES +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values +# (range [0,1..20]) that doxygen will group on one line in the generated HTML +# documentation. Note that a value of 0 will completely suppress the enum +# values from appearing in the overview section. + +ENUM_VALUES_PER_LINE = 1 + # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open +# links to external symbols imported via tag files in a separate window. + +EXT_LINKS_IN_WINDOW = NO + # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need @@ -886,6 +1155,60 @@ TREEVIEW_WIDTH = 250 FORMULA_FONTSIZE = 10 +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are +# not supported properly for IE 6.0, but are supported on all modern browsers. +# Note that when changing this option you need to delete any form_*.png files +# in the HTML output before the changes have effect. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax +# (see http://www.mathjax.org) which uses client side Javascript for the +# rendering instead of using prerendered bitmaps. Use this if you do not +# have LaTeX installed or if you want to formulas look prettier in the HTML +# output. When enabled you may also need to install MathJax separately and +# configure the path to it using the MATHJAX_RELPATH option. + +USE_MATHJAX = NO + +# When MathJax is enabled you need to specify the location relative to the +# HTML output directory using the MATHJAX_RELPATH option. The destination +# directory should contain the MathJax.js script. For instance, if the mathjax +# directory is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to +# the MathJax Content Delivery Network so you can quickly see the result without +# installing MathJax. +# However, it is strongly recommended to install a local +# copy of MathJax from http://www.mathjax.org before deployment. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension +# names that should be enabled during MathJax rendering. + +MATHJAX_EXTENSIONS = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box +# for the HTML output. The underlying search engine uses javascript +# and DHTML and should work on any modern browser. Note that when using +# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets +# (GENERATE_DOCSET) there is already a search function so this one should +# typically be disabled. For large projects the javascript based search engine +# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. + +SEARCHENGINE = NO + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a PHP enabled web server instead of at the web client +# using Javascript. Doxygen will generate the search PHP script and index +# file to put on the web server. The advantage of the server +# based approach is that it scales better to large projects and allows +# full text search. The disadvantages are that it is more difficult to setup +# and does not have live searching capabilities. + +SERVER_BASED_SEARCH = NO + #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- @@ -903,6 +1226,9 @@ LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. +# Note that when enabling USE_PDFLATEX this option is only used for +# generating bitmaps for formulas in the HTML output, but not in the +# Makefile that is written to the output directory. LATEX_CMD_NAME = latex @@ -919,7 +1245,7 @@ MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used -# by the printer. Possible values are: a4, a4wide, letter, legal and +# by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide @@ -936,6 +1262,13 @@ EXTRA_PACKAGES = LATEX_HEADER = +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for +# the generated latex document. The footer should contain everything after +# the last chapter. If it is left blank doxygen will generate a +# standard footer. Notice: only use this tag if you know what you are doing! + +LATEX_FOOTER = + # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references @@ -962,6 +1295,19 @@ LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO +# If LATEX_SOURCE_CODE is set to YES then doxygen will include +# source code with syntax highlighting in the LaTeX output. +# Note that which sources are shown also depends on other settings +# such as SOURCE_BROWSER. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See +# http://en.wikipedia.org/wiki/BibTeX for more info. + +LATEX_BIB_STYLE = plain + #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- @@ -993,7 +1339,7 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's +# Load style sheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. @@ -1098,8 +1444,10 @@ GENERATE_PERLMOD = NO PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be -# nicely formatted so it can be parsed by a human reader. This is useful -# if you want to understand what is going on. On the other hand, if this +# nicely formatted so it can be parsed by a human reader. +# This is useful +# if you want to understand what is going on. +# On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. @@ -1136,7 +1484,7 @@ MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files -# in the INCLUDE_PATH (see below) will be search if a #include is found. +# pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES @@ -1161,20 +1509,20 @@ INCLUDE_FILE_PATTERNS = # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = LEAK_DETECTIVE +PREDEFINED = LEAK_DETECTIVE __attribute__(x)= # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. -# Use the PREDEFINED tag if you want to use a different macro definition. +# Use the PREDEFINED tag if you want to use a different macro definition that +# overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then -# doxygen's preprocessor will remove all function-like macros that are alone -# on a line, have an all uppercase name, and do not end with a semicolon. Such -# function macros are typically used for boiler-plate code, and will confuse -# the parser if not removed. +# doxygen's preprocessor will remove all references to function-like macros +# that are alone on a line, have an all uppercase name, and do not end with a +# semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES @@ -1182,20 +1530,18 @@ SKIP_FUNCTION_MACROS = YES # Configuration::additions related to external references #--------------------------------------------------------------------------- -# The TAGFILES option can be used to specify one or more tagfiles. -# Optionally an initial location of the external documentation -# can be added for each tagfile. The format of a tag file without -# this location is as follows: -# TAGFILES = file1 file2 ... +# The TAGFILES option can be used to specify one or more tagfiles. For each +# tag file the location of the external documentation should be added. The +# format of a tag file without this location is as follows: +# +# TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: -# TAGFILES = file1=loc1 "file2 = loc2" ... -# where "loc1" and "loc2" can be relative or absolute paths or -# URLs. If a location is present for each tag, the installdox tool -# does not have to be run to correct the links. -# Note that each tag file must have a unique name -# (where the name does NOT include the path) -# If a tag file is not located in the directory in which doxygen -# is run, you must also specify the path to the tagfile here. +# +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths +# or URLs. Note that each tag file must have a unique name (where the name does +# NOT include the path). If a tag file is not located in the directory in which +# doxygen is run, you must also specify the path to the tagfile here. TAGFILES = @@ -1228,9 +1574,8 @@ PERL_PATH = /usr/bin/perl # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that -# this option is superseded by the HAVE_DOT option below. This is only a -# fallback. It is recommended to install and use dot, since it yields more -# powerful graphs. +# this option also works with HAVE_DOT disabled, but it is recommended to +# install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES @@ -1256,28 +1601,38 @@ HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO -# By default doxygen will write a font called FreeSans.ttf to the output -# directory and reference it in all dot files that doxygen generates. This -# font does not include all possible unicode characters however, so when you need -# these (or just want a differently looking font) you can specify the font name -# using DOT_FONTNAME. You need need to make sure dot is able to find the font, -# which can be done by putting it in a standard location or by setting the -# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory -# containing the font. +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is +# allowed to run in parallel. When set to 0 (the default) doxygen will +# base this on the number of processors available in the system. You can set it +# explicitly to a value larger than 0 to get control over the balance +# between CPU load and processing speed. + +DOT_NUM_THREADS = 0 + +# By default doxygen will use the Helvetica font for all dot files that +# doxygen generates. When you want a differently looking font you can specify +# the font name using DOT_FONTNAME. You need to make sure dot is able to find +# the font, which can be done by putting it in a standard location or by setting +# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. DOT_FONTNAME = FreeSans -# By default doxygen will tell dot to use the output directory to look for the -# FreeSans.ttf font (which doxygen will put there itself). If you specify a -# different font using DOT_FONTNAME you can set the path where dot -# can find it using this tag. +# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. +# The default size is 10pt. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the Helvetica font. +# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to +# set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the -# the CLASS_DIAGRAMS tag to NO. +# CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES @@ -1299,6 +1654,15 @@ GROUP_GRAPHS = YES UML_LOOK = NO +# If the UML_LOOK tag is enabled, the fields and methods are shown inside +# the class node. If there are many fields or methods and many nodes the +# graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS +# threshold limits the number of items for each type to make the size more +# managable. Set this to 0 for no limit. Note that the threshold may be +# exceeded by 50% before the limit is enforced. + +UML_LIMIT_NUM_FIELDS = 10 + # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. @@ -1335,11 +1699,11 @@ CALL_GRAPH = NO CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen -# will graphical hierarchy of all classes instead of a textual one. +# will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES -# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# If the DIRECTORY_GRAPH and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. @@ -1347,11 +1711,22 @@ GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. Possible values are png, jpg, or gif -# If left blank png will be used. +# generated by dot. Possible values are svg, png, jpg, or gif. +# If left blank png will be used. If you choose svg you need to set +# HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# Note that this requires a modern browser other than Internet Explorer. +# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you +# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files +# visible. Older versions of IE do not have SVG support. + +INTERACTIVE_SVG = NO + # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. @@ -1363,6 +1738,12 @@ DOT_PATH = DOTFILE_DIRS = +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the +# \mscfile command). + +MSCFILE_DIRS = + # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is @@ -1384,10 +1765,10 @@ DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is enabled by default, which results in a transparent -# background. Warning: Depending on the platform used, enabling this option -# may lead to badly anti-aliased labels on the edges of a graph (i.e. they -# become hard to read). +# background. This is disabled by default, because dot on Windows does not +# seem to support this out of the box. Warning: Depending on the platform used, +# enabling this option may lead to badly anti-aliased labels on the edges of +# a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO @@ -1409,12 +1790,3 @@ GENERATE_LEGEND = YES # the various graphs. DOT_CLEANUP = YES - -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- - -# The SEARCHENGINE tag specifies whether or not a search engine should be -# used. If set to NO the values of all tags below this one will be ignored. - -SEARCHENGINE = NO @@ -1,3 +1,20 @@ +strongswan-5.0.3 +---------------- + +- The new ipseckey plugin enables authentication based on trustworthy public + keys stored as IPSECKEY resource records in the DNS and protected by DNSSEC. + To do so it uses a DNSSEC enabled resolver, like the one provided by the new + unbound plugin, which is based on libldns and libunbound. Both plugins were + created by Reto Guadagnini. + +- Implemented the TCG TNC IF-IMV 1.4 draft making access requestor identities + available to an IMV. The OS IMV stores the AR identity together with the + device ID in the attest database. + +- The openssl plugin now uses the AES-NI accelerated version of AES-GCM + if the hardware supports it. + + strongswan-5.0.2 ---------------- @@ -49,6 +66,7 @@ strongswan-5.0.2 - The integration test environment was updated and now uses KVM and reproducible guest images based on Debian. + strongswan-5.0.1 ---------------- @@ -122,6 +140,7 @@ strongswan-5.0.1 - All crypto primitives gained return values for most operations, allowing crypto backends to fail, for example when using hardware accelerators. + strongswan-5.0.0 ---------------- diff --git a/configure.in b/configure.in index 2c3e739d6..996c8dd9c 100644 --- a/configure.in +++ b/configure.in @@ -1,31 +1,34 @@ -dnl configure.in for linux strongSwan -dnl Copyright (C) 2006 Martin Willi -dnl Hochschule fuer Technik Rapperswil -dnl -dnl This program is free software; you can redistribute it and/or modify it -dnl under the terms of the GNU General Public License as published by the -dnl Free Software Foundation; either version 2 of the License, or (at your -dnl option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. -dnl -dnl This program is distributed in the hope that it will be useful, but -dnl WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -dnl or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -dnl for more details. - -dnl =========================== -dnl initialize & set some vars -dnl =========================== - -AC_INIT(strongSwan,5.0.2) +# +# Copyright (C) 2007-2013 Tobias Brunner +# Copyright (C) 2006-2013 Andreas Steffen +# Copyright (C) 2006-2013 Martin Willi +# 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. +# + +# ============================ +# initialize & set some vars +# ============================ + +AC_INIT([strongSwan],[5.0.3dr4]) AM_INIT_AUTOMAKE(tar-ustar) AC_CONFIG_MACRO_DIR([m4/config]) AC_CONFIG_HEADERS([config.h]) AC_DEFINE([CONFIG_H_INCLUDED], [], [defined if config.h included]) PKG_PROG_PKG_CONFIG -dnl ================================= -dnl check --enable-xxx & --with-xxx -dnl ================================= +# ================================= +# check --enable-xxx & --with-xxx +# ================================= m4_include(m4/macros/with.m4) @@ -101,6 +104,7 @@ AC_SUBST(ipsec_script_upper, [`echo -n "$ipsec_script" | tr a-z A-Z`]) m4_include(m4/macros/enable-disable.m4) ARG_ENABL_SET([curl], [enable CURL fetcher plugin to fetch files via libcurl. Requires libcurl.]) +ARG_ENABL_SET([unbound], [enable UNBOUND resolver plugin to perform DNS queries via libunbound. Requires libldns and libunbound.]) ARG_ENABL_SET([soup], [enable soup fetcher plugin to fetch from HTTP via libsoup. Requires libsoup.]) ARG_ENABL_SET([ldap], [enable LDAP fetching plugin to fetch files via libldap. Requires openLDAP.]) ARG_DISBL_SET([aes], [disable AES software implementation plugin.]) @@ -124,6 +128,7 @@ ARG_DISBL_SET([pkcs7], [disable PKCS7 container support plugin.]) ARG_DISBL_SET([pkcs8], [disable PKCS8 private key decoding plugin.]) ARG_DISBL_SET([pgp], [disable PGP key decoding plugin.]) ARG_DISBL_SET([dnskey], [disable DNS RR key decoding plugin.]) +ARG_ENABL_SET([ipseckey], [enable IPSECKEY authentication plugin.]) ARG_DISBL_SET([pem], [disable PEM decoding plugin.]) ARG_DISBL_SET([hmac], [disable HMAC crypto implementation plugin.]) ARG_DISBL_SET([cmac], [disable CMAC crypto implementation plugin.]) @@ -213,7 +218,7 @@ ARG_ENABL_SET([gcm], [enables the GCM AEAD wrapper crypto plugin.]) ARG_ENABL_SET([addrblock], [enables RFC 3779 address block constraint support.]) ARG_ENABL_SET([unity], [enables Cisco Unity extension plugin.]) ARG_ENABL_SET([uci], [enable OpenWRT UCI configuration plugin.]) -ARG_ENABL_SET([android], [enable Android specific plugin.]) +ARG_ENABL_SET([android-dns], [enable Android specific DNS handler.]) ARG_ENABL_SET([android-log], [enable Android specific logger plugin.]) ARG_ENABL_SET([maemo], [enable Maemo specific plugin.]) ARG_ENABL_SET([nm], [enable NetworkManager backend.]) @@ -222,6 +227,7 @@ ARG_ENABL_SET([whitelist], [enable peer identity whitelisting plugin.]) ARG_ENABL_SET([lookip], [enable fast virtual IP lookup and notification plugin.]) ARG_ENABL_SET([error-notify], [enable error notification plugin.]) ARG_ENABL_SET([certexpire], [enable CSV export of expiration dates of used certificates.]) +ARG_ENABL_SET([systime-fix], [enable plugin to handle cert lifetimes with invalid system time gracefully.]) ARG_ENABL_SET([led], [enable plugin to control LEDs on IKEv2 activity using the Linux kernel LED subsystem.]) ARG_ENABL_SET([duplicheck], [advanced duplicate checking plugin using liveness checks.]) ARG_ENABL_SET([coupling], [enable IKEv2 plugin to couple peer certificates permanently to authentication.]) @@ -230,9 +236,22 @@ ARG_ENABL_SET([vstr], [enforce using the Vstr string library to replac ARG_ENABL_SET([monolithic], [build monolithic version of libstrongswan that includes all enabled plugins. Similarly, the plugins of charon are assembled in libcharon.]) ARG_ENABL_SET([bfd-backtraces], [use binutils libbfd to resolve backtraces for memory leaks and segfaults.]) -dnl ========================= -dnl set up compiler and flags -dnl ========================= +# =================================== +# option to disable default options +# =================================== + +ARG_DISBL_SET([defaults], [disable all default plugins (they can be enabled with their respective --enable options)]) + +if test x$defaults = xfalse; then + for option in $enabled_by_default; do + eval test x\${${option}_given} = xtrue && continue + let $option=false + done +fi + +# =========================== +# set up compiler and flags +# =========================== if test -z "$CFLAGS"; then CFLAGS="-g -O2 -Wall -Wno-format -Wno-pointer-sign" @@ -241,12 +260,12 @@ AC_PROG_CC AC_LIB_PREFIX AC_C_BIGENDIAN -dnl ========================= -dnl check required programs -dnl ========================= +# ========================= +# check required programs +# ========================= +LT_INIT AC_PROG_INSTALL -AC_PROG_LIBTOOL AC_PROG_EGREP AC_PROG_AWK AC_PROG_LEX @@ -254,7 +273,7 @@ AC_PROG_YACC AC_PATH_PROG([PERL], [perl], [], [$PATH:/bin:/usr/bin:/usr/local/bin]) AC_PATH_PROG([GPERF], [gperf], [], [$PATH:/bin:/usr/bin:/usr/local/bin]) -dnl because gperf is not needed by end-users we just report it but do not abort on failure +# because gperf is not needed by end-users we just report it but do not abort on failure AC_MSG_CHECKING([gperf version >= 3.0.0]) if test -x "$GPERF"; then if test "`$GPERF --version | $AWK -F' ' '/^GNU gperf/ { print $3 }' | $AWK -F. '{ print $1 }'`" -ge "3"; then @@ -266,9 +285,9 @@ else AC_MSG_RESULT([not found]) fi -dnl ========================= -dnl dependency calculation -dnl ========================= +# ======================== +# dependency calculation +# ======================== if test x$xauth_generic_given = xfalse -a x$ikev1 = xfalse; then xauth_generic=false; @@ -335,91 +354,93 @@ if test x$medcli = xtrue; then mediation=true fi -dnl =========================================== -dnl check required libraries and header files -dnl =========================================== +# =========================================== +# check required libraries and header files +# =========================================== AC_HEADER_STDBOOL AC_FUNC_ALLOCA AC_FUNC_STRERROR_R -dnl libraries needed on some platforms but not on others -dnl ==================================================== +# libraries needed on some platforms but not on others +# ------------------------------------------------------ saved_LIBS=$LIBS -dnl FreeBSD and Mac OS X have dlopen integrated in libc, Linux needs libdl +# FreeBSD and Mac OS X have dlopen integrated in libc, Linux needs libdl LIBS="" AC_SEARCH_LIBS(dlopen, dl, [DLLIB=$LIBS]) AC_SUBST(DLLIB) -dnl glibc's backtrace() can be replicated on FreeBSD with libexecinfo +# glibc's backtrace() can be replicated on FreeBSD with libexecinfo LIBS="" AC_SEARCH_LIBS(backtrace, execinfo, [BTLIB=$LIBS]) AC_CHECK_FUNCS(backtrace) AC_SUBST(BTLIB) -dnl OpenSolaris needs libsocket and libnsl for socket() +# OpenSolaris needs libsocket and libnsl for socket() LIBS="" AC_SEARCH_LIBS(socket, socket, [SOCKLIB=$LIBS], [AC_CHECK_LIB(nsl, socket, [SOCKLIB="-lsocket -lnsl"], [], [-lsocket])] ) AC_SUBST(SOCKLIB) -dnl FreeBSD has clock_gettime in libc, Linux needs librt +# FreeBSD has clock_gettime in libc, Linux needs librt LIBS="" AC_SEARCH_LIBS(clock_gettime, rt, [RTLIB=$LIBS]) AC_CHECK_FUNCS(clock_gettime) AC_SUBST(RTLIB) -dnl Android has pthread_* functions in bionic (libc), others need libpthread +# Android has pthread_* functions in bionic (libc), others need libpthread LIBS="" AC_SEARCH_LIBS(pthread_create, pthread, [PTHREADLIB=$LIBS]) AC_SUBST(PTHREADLIB) LIBS=$saved_LIBS -dnl ====================== +# ------------------------------------------------------ AC_MSG_CHECKING(for dladdr) -AC_TRY_COMPILE( - [#define _GNU_SOURCE - #include <dlfcn.h>], - [Dl_info* info = 0; - dladdr(0, info);], +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#define _GNU_SOURCE + #include <dlfcn.h>]], + [[Dl_info* info = 0; + dladdr(0, info);]])], [AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_DLADDR], [], [have dladdr()])], [AC_MSG_RESULT([no])] ) -dnl check if pthread_condattr_setclock(CLOCK_MONOTONE) is supported +# check if pthread_condattr_setclock(CLOCK_MONOTONE) is supported saved_LIBS=$LIBS LIBS=$PTHREADLIB AC_MSG_CHECKING([for pthread_condattr_setclock(CLOCK_MONOTONE)]) -AC_TRY_RUN( - [#include <pthread.h> - int main() { pthread_condattr_t attr; - pthread_condattr_init(&attr); - return pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);}], +AC_RUN_IFELSE( + [AC_LANG_SOURCE( + [[#include <pthread.h> + int main() { pthread_condattr_t attr; + pthread_condattr_init(&attr); + return pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);}]])], [AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_CONDATTR_CLOCK_MONOTONIC], [], [pthread_condattr_setclock supports CLOCK_MONOTONIC])], [AC_MSG_RESULT([no])], - dnl Check existence of pthread_condattr_setclock if cross-compiling + # Check existence of pthread_condattr_setclock if cross-compiling [AC_MSG_RESULT([unknown]); AC_CHECK_FUNCS(pthread_condattr_setclock, [AC_DEFINE([HAVE_CONDATTR_CLOCK_MONOTONIC], [], [have pthread_condattr_setclock()])] )] ) -dnl check if we actually are able to configure attributes on cond vars +# check if we actually are able to configure attributes on cond vars AC_CHECK_FUNCS(pthread_condattr_init) -dnl instead of pthread_condattr_setclock Android has this function +# instead of pthread_condattr_setclock Android has this function AC_CHECK_FUNCS(pthread_cond_timedwait_monotonic) -dnl check if we can cancel threads +# check if we can cancel threads AC_CHECK_FUNCS(pthread_cancel) -dnl check if native rwlocks are available +# check if native rwlocks are available AC_CHECK_FUNCS(pthread_rwlock_init) -dnl check if pthread spinlocks are available +# check if pthread spinlocks are available AC_CHECK_FUNCS(pthread_spin_init) -dnl check if we have POSIX semaphore functions, including timed-wait +# check if we have POSIX semaphore functions, including timed-wait AC_CHECK_FUNCS(sem_timedwait) LIBS=$saved_LIBS @@ -427,12 +448,13 @@ AC_CHECK_FUNC( [gettid], [AC_DEFINE([HAVE_GETTID], [], [have gettid()])], [AC_MSG_CHECKING([for SYS_gettid]) - AC_TRY_COMPILE( - [#define _GNU_SOURCE - #include <unistd.h> - #include <sys/syscall.h>], - [int main() { - return syscall(SYS_gettid);}], + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#define _GNU_SOURCE + #include <unistd.h> + #include <sys/syscall.h>]], + [[int main() { + return syscall(SYS_gettid);}]])], [AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_GETTID], [], [have gettid()]) AC_DEFINE([HAVE_SYS_GETTID], [], [have syscall(SYS_gettid)])], @@ -440,7 +462,7 @@ AC_CHECK_FUNC( )] ) -AC_CHECK_FUNCS(prctl mallinfo getpass closefrom getpwnam_r getgrnam_r) +AC_CHECK_FUNCS(prctl mallinfo getpass closefrom getpwnam_r getgrnam_r getpwuid_r) AC_CHECK_HEADERS(sys/sockio.h glob.h) AC_CHECK_HEADERS(net/pfkeyv2.h netipsec/ipsec.h netinet6/ipsec.h linux/udp.h) @@ -464,101 +486,107 @@ AC_CHECK_MEMBERS([struct sadb_x_policy.sadb_x_policy_priority], [], [], ]) AC_MSG_CHECKING([for in6addr_any]) -AC_TRY_COMPILE( - [#include <sys/types.h> - #include <sys/socket.h> - #include <netinet/in.h>], - [struct in6_addr in6; - in6 = in6addr_any;], +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h>]], + [[struct in6_addr in6; + in6 = in6addr_any;]])], [AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_IN6ADDR_ANY], [], [have struct in6_addr in6addr_any])], [AC_MSG_RESULT([no])] ) AC_MSG_CHECKING([for in6_pktinfo]) -AC_TRY_COMPILE( - [#define _GNU_SOURCE - #include <sys/types.h> - #include <sys/socket.h> - #include <netinet/in.h>], - [struct in6_pktinfo pi; - if (pi.ipi6_ifindex) - { - return 0; - }], +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#define _GNU_SOURCE + #include <sys/types.h> + #include <sys/socket.h> + #include <netinet/in.h>]], + [[struct in6_pktinfo pi; + if (pi.ipi6_ifindex) + { + return 0; + }]])], [AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_IN6_PKTINFO], [], [have struct in6_pktinfo.ipi6_ifindex])], [AC_MSG_RESULT([no])] ) AC_MSG_CHECKING([for IPSEC_MODE_BEET]) -AC_TRY_COMPILE( - [#include <sys/types.h> - #ifdef HAVE_NETIPSEC_IPSEC_H - #include <netipsec/ipsec.h> - #elif defined(HAVE_NETINET6_IPSEC_H) - #include <netinet6/ipsec.h> - #else - #include <stdint.h> - #include <linux/ipsec.h> - #endif], - [int mode = IPSEC_MODE_BEET; - return mode;], +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <sys/types.h> + #ifdef HAVE_NETIPSEC_IPSEC_H + #include <netipsec/ipsec.h> + #elif defined(HAVE_NETINET6_IPSEC_H) + #include <netinet6/ipsec.h> + #else + #include <stdint.h> + #include <linux/ipsec.h> + #endif]], + [[int mode = IPSEC_MODE_BEET; + return mode;]])], [AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_IPSEC_MODE_BEET], [], [have IPSEC_MODE_BEET defined])], [AC_MSG_RESULT([no])] ) AC_MSG_CHECKING([for IPSEC_DIR_FWD]) -AC_TRY_COMPILE( - [#include <sys/types.h> - #ifdef HAVE_NETIPSEC_IPSEC_H - #include <netipsec/ipsec.h> - #elif defined(HAVE_NETINET6_IPSEC_H) - #include <netinet6/ipsec.h> - #else - #include <stdint.h> - #include <linux/ipsec.h> - #endif], - [int dir = IPSEC_DIR_FWD; - return dir;], +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <sys/types.h> + #ifdef HAVE_NETIPSEC_IPSEC_H + #include <netipsec/ipsec.h> + #elif defined(HAVE_NETINET6_IPSEC_H) + #include <netinet6/ipsec.h> + #else + #include <stdint.h> + #include <linux/ipsec.h> + #endif]], + [[int dir = IPSEC_DIR_FWD; + return dir;]])], [AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_IPSEC_DIR_FWD], [], [have IPSEC_DIR_FWD defined])], [AC_MSG_RESULT([no])] ) AC_MSG_CHECKING([for RTA_TABLE]) -AC_TRY_COMPILE( - [#include <sys/socket.h> - #include <linux/netlink.h> - #include <linux/rtnetlink.h>], - [int rta_type = RTA_TABLE; - return rta_type;], +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <sys/socket.h> + #include <linux/netlink.h> + #include <linux/rtnetlink.h>]], + [[int rta_type = RTA_TABLE; + return rta_type;]])], [AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_RTA_TABLE], [], [have netlink RTA_TABLE defined])], [AC_MSG_RESULT([no])] ) AC_MSG_CHECKING([for gcc atomic operations]) -AC_TRY_RUN( -[ - int main() { - volatile int ref = 1; - __sync_fetch_and_add (&ref, 1); - __sync_sub_and_fetch (&ref, 1); - /* Make sure test fails if operations are not supported */ - __sync_val_compare_and_swap(&ref, 1, 0); - return ref; - } -], -[AC_MSG_RESULT([yes]); - AC_DEFINE([HAVE_GCC_ATOMIC_OPERATIONS], [], +AC_RUN_IFELSE([AC_LANG_SOURCE( + [[ + int main() { + volatile int ref = 1; + __sync_fetch_and_add (&ref, 1); + __sync_sub_and_fetch (&ref, 1); + /* Make sure test fails if operations are not supported */ + __sync_val_compare_and_swap(&ref, 1, 0); + return ref; + } + ]])], + [AC_MSG_RESULT([yes]); + AC_DEFINE([HAVE_GCC_ATOMIC_OPERATIONS], [], [have GCC __sync_* atomic operations])], -[AC_MSG_RESULT([no])], -[AC_MSG_RESULT([no])]) + [AC_MSG_RESULT([no])], + [AC_MSG_RESULT([no])] +) -dnl check for the new register_printf_specifier function with len argument, -dnl or the deprecated register_printf_function without +# check for the new register_printf_specifier function with len argument, +# or the deprecated register_printf_function without AC_CHECK_FUNC( [register_printf_specifier], [AC_DEFINE([HAVE_PRINTF_SPECIFIER], [], [have register_printf_specifier()])], @@ -573,20 +601,19 @@ AC_CHECK_FUNC( ) if test x$vstr = xtrue; then - AC_HAVE_LIBRARY([vstr],[LIBS="$LIBS"],[AC_MSG_ERROR([Vstr string library not found])]) + AC_CHECK_LIB([vstr],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([Vstr string library not found])],[]) AC_DEFINE([USE_VSTR], [], [use vstring library for printf hooks]) fi if test x$gmp = xtrue; then saved_LIBS=$LIBS - AC_HAVE_LIBRARY([gmp],,[AC_MSG_ERROR([GNU Multi Precision library gmp not found])]) + AC_CHECK_LIB([gmp],[main],[],[AC_MSG_ERROR([GNU Multi Precision library gmp not found])],[]) AC_MSG_CHECKING([mpz_powm_sec]) if test x$mpz_powm_sec = xyes; then - AC_TRY_COMPILE( - [#include "gmp.h"], - [ - void *x = mpz_powm_sec; - ], + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include "gmp.h"]], + [[void *x = mpz_powm_sec;]])], [AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_MPZ_POWM_SEC], [], [have mpz_mown_sec()])], [AC_MSG_RESULT([no])] @@ -596,28 +623,36 @@ if test x$gmp = xtrue; then fi LIBS=$saved_LIBS AC_MSG_CHECKING([gmp.h version >= 4.1.4]) - AC_TRY_COMPILE( - [#include "gmp.h"], - [ - #if (__GNU_MP_VERSION*100 + __GNU_MP_VERSION_MINOR*10 + __GNU_MP_VERSION_PATCHLEVEL) < 414 - #error bad gmp - #endif - ], - [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]); AC_MSG_ERROR([No usable gmp.h found!])] + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include "gmp.h"]], + [[ + #if (__GNU_MP_VERSION*100 + __GNU_MP_VERSION_MINOR*10 + __GNU_MP_VERSION_PATCHLEVEL) < 414 + #error bad gmp + #endif]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]); AC_MSG_ERROR([No usable gmp.h found!])] ) fi if test x$ldap = xtrue; then - AC_HAVE_LIBRARY([ldap],[LIBS="$LIBS"],[AC_MSG_ERROR([LDAP library ldap not found])]) - AC_HAVE_LIBRARY([lber],[LIBS="$LIBS"],[AC_MSG_ERROR([LDAP library lber not found])]) + AC_CHECK_LIB([ldap],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([LDAP library ldap not found])],[]) + AC_CHECK_LIB([lber],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([LDAP library lber not found])],[]) AC_CHECK_HEADER([ldap.h],,[AC_MSG_ERROR([LDAP header ldap.h not found!])]) fi if test x$curl = xtrue; then - AC_HAVE_LIBRARY([curl],[LIBS="$LIBS"],[AC_MSG_ERROR([CURL library curl not found])]) + AC_CHECK_LIB([curl],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([CURL library curl not found])],[]) AC_CHECK_HEADER([curl/curl.h],,[AC_MSG_ERROR([CURL header curl/curl.h not found!])]) fi +if test x$unbound = xtrue; then + AC_HAVE_LIBRARY([ldns],[LIBS="$LIBS"],[AC_MSG_ERROR([UNBOUND library ldns not found])]) + AC_CHECK_HEADER([ldns/ldns.h],,[AC_MSG_ERROR([UNBOUND header ldns/ldns.h not found!])]) + AC_HAVE_LIBRARY([unbound],[LIBS="$LIBS"],[AC_MSG_ERROR([UNBOUND library libunbound not found])]) + AC_CHECK_HEADER([unbound.h],,[AC_MSG_ERROR([UNBOUND header unbound.h not found!])]) +fi + if test x$soup = xtrue; then PKG_CHECK_MODULES(soup, [libsoup-2.4]) AC_SUBST(soup_CFLAGS) @@ -637,7 +672,7 @@ if test x$axis2c = xtrue; then fi if test x$tss = xtrousers; then - AC_HAVE_LIBRARY([tspi],[LIBS="$LIBS"],[AC_MSG_ERROR([TrouSerS library libtspi not found])]) + AC_CHECK_LIB([tspi],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([TrouSerS library libtspi not found])],[]) AC_CHECK_HEADER([trousers/tss.h],,[AC_MSG_ERROR([TrouSerS header trousers/tss.h not found!])]) AC_DEFINE([TSS_TROUSERS], [], [use TrouSerS library libtspi as TSS implementation]) fi @@ -683,28 +718,27 @@ if test x$dumm = xtrue; then fi if test x$fast = xtrue; then - AC_HAVE_LIBRARY([neo_cgi],[LIBS="$LIBS"],[AC_MSG_ERROR([ClearSilver library neo_cgi not found!])]) - AC_HAVE_LIBRARY([neo_utl],[LIBS="$LIBS"],[AC_MSG_ERROR([ClearSilver library neo_utl not found!])]) + AC_CHECK_LIB([neo_cgi],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([ClearSilver library neo_cgi not found!])],[]) + AC_CHECK_LIB([neo_utl],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([ClearSilver library neo_utl not found!])],[]) AC_MSG_CHECKING([ClearSilver requires zlib]) saved_CFLAGS=$CFLAGS saved_LIBS=$LIBS LIBS="-lneo_cgi -lneo_cs -lneo_utl" CFLAGS="-I/usr/include/ClearSilver" - AC_TRY_LINK( - [#include <ClearSilver.h>], - [ - NEOERR *err = cgi_display(NULL, NULL); - ], + AC_LINK_IFELSE( + [AC_LANG_PROGRAM( + [[#include <ClearSilver.h>]], + [[NEOERR *err = cgi_display(NULL, NULL);]])], [AC_MSG_RESULT([no]); clearsilver_LIBS="$LIBS"], [AC_MSG_RESULT([yes]); clearsilver_LIBS="$LIBS -lz"] ) AC_SUBST(clearsilver_LIBS) LIBS=$saved_LIBS CFLAGS=$saved_CFLAGS -dnl autoconf does not like CamelCase!? How to fix this? -dnl AC_CHECK_HEADER([ClearSilver/ClearSilver.h],,[AC_MSG_ERROR([ClearSilver header file ClearSilver/ClearSilver.h not found!])]) +# autoconf does not like CamelCase!? How to fix this? +# AC_CHECK_HEADER([ClearSilver/ClearSilver.h],,[AC_MSG_ERROR([ClearSilver header file ClearSilver/ClearSilver.h not found!])]) - AC_HAVE_LIBRARY([fcgi],[LIBS="$LIBS"],[AC_MSG_ERROR([FastCGI library fcgi not found!])]) + AC_CHECK_LIB([fcgi],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([FastCGI library fcgi not found!])],[]) AC_CHECK_HEADER([fcgiapp.h],,[AC_MSG_ERROR([FastCGI header file fcgiapp.h not found!])]) fi @@ -718,40 +752,43 @@ if test x$mysql = xtrue; then fi if test x$sqlite = xtrue; then - AC_HAVE_LIBRARY([sqlite3],[LIBS="$LIBS"],[AC_MSG_ERROR([SQLite library sqlite3 not found])]) + AC_CHECK_LIB([sqlite3],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([SQLite library sqlite3 not found])],[]) AC_CHECK_HEADER([sqlite3.h],,[AC_MSG_ERROR([SQLite header sqlite3.h not found!])]) AC_MSG_CHECKING([sqlite3_prepare_v2]) - AC_TRY_COMPILE( - [#include <sqlite3.h>], - [ - void *test = sqlite3_prepare_v2; - ], - [AC_MSG_RESULT([yes])]; - AC_DEFINE([HAVE_SQLITE3_PREPARE_V2], [], [have sqlite3_prepare_v2()]), - [AC_MSG_RESULT([no])]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <sqlite3.h>]], + [[void *test = sqlite3_prepare_v2;]])], + [AC_MSG_RESULT([yes]); + AC_DEFINE([HAVE_SQLITE3_PREPARE_V2], [], [have sqlite3_prepare_v2()])], + [AC_MSG_RESULT([no])] + ) AC_MSG_CHECKING([sqlite3.h version >= 3.3.1]) - AC_TRY_COMPILE( - [#include <sqlite3.h>], - [ - #if SQLITE_VERSION_NUMBER < 3003001 - #error bad sqlite - #endif - ], - [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]); AC_MSG_ERROR([SQLite version >= 3.3.1 required!])]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <sqlite3.h>]], + [[ + #if SQLITE_VERSION_NUMBER < 3003001 + #error bad sqlite + #endif]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]); AC_MSG_ERROR([SQLite version >= 3.3.1 required!])] + ) fi if test x$openssl = xtrue; then - AC_HAVE_LIBRARY([crypto],[LIBS="$LIBS"],[AC_MSG_ERROR([OpenSSL crypto library not found])]) + AC_CHECK_LIB([crypto],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([OpenSSL crypto library not found])],[]) AC_CHECK_HEADER([openssl/evp.h],,[AC_MSG_ERROR([OpenSSL header openssl/evp.h not found!])]) fi if test x$gcrypt = xtrue; then - AC_HAVE_LIBRARY([gcrypt],[LIBS="$LIBS"],[AC_MSG_ERROR([gcrypt library not found])],[-lgpg-error]) + AC_CHECK_LIB([gcrypt],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([gcrypt library not found])],[-lgpg-error]) AC_CHECK_HEADER([gcrypt.h],,[AC_MSG_ERROR([gcrypt header gcrypt.h not found!])]) AC_MSG_CHECKING([gcrypt CAMELLIA cipher]) - AC_TRY_COMPILE( - [#include <gcrypt.h>], - [enum gcry_cipher_algos alg = GCRY_CIPHER_CAMELLIA128;], + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include <gcrypt.h>]], + [[enum gcry_cipher_algos alg = GCRY_CIPHER_CAMELLIA128;]])], [AC_MSG_RESULT([yes]); AC_DEFINE([HAVE_GCRY_CIPHER_CAMELLIA], [], [have GCRY_CIPHER_CAMELLIA128])], [AC_MSG_RESULT([no])] @@ -759,15 +796,15 @@ if test x$gcrypt = xtrue; then fi if test x$uci = xtrue; then - AC_HAVE_LIBRARY([uci],[LIBS="$LIBS"],[AC_MSG_ERROR([UCI library libuci not found])]) + AC_CHECK_LIB([uci],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([UCI library libuci not found])],[]) AC_CHECK_HEADER([uci.h],,[AC_MSG_ERROR([UCI header uci.h not found!])]) fi -if test x$android = xtrue; then - AC_HAVE_LIBRARY([cutils],[LIBS="$LIBS"],[AC_MSG_ERROR([Android library libcutils not found])]) +if test x$android_dns = xtrue; then + AC_CHECK_LIB([cutils],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([Android library libcutils not found])],[]) AC_CHECK_HEADER([cutils/properties.h],,[AC_MSG_ERROR([Android header cutils/properties.h not found!])]) - dnl we have to force the use of libdl here because the autodetection - dnl above does not work correctly when cross-compiling for android. + # we have to force the use of libdl here because the autodetection + # above does not work correctly when cross-compiling for android. DLLIB="-ldl" AC_SUBST(DLLIB) fi @@ -796,21 +833,21 @@ if test x$nm = xtrue; then fi if test x$xauth_pam = xtrue; then - AC_HAVE_LIBRARY([pam],[LIBS="$LIBS"],[AC_MSG_ERROR([PAM library not found])]) + AC_CHECK_LIB([pam],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([PAM library not found])],[]) AC_CHECK_HEADER([security/pam_appl.h],,[AC_MSG_ERROR([PAM header security/pam_appl.h not found!])]) fi if test x$capabilities = xnative; then AC_MSG_NOTICE([Usage of the native Linux capabilities interface is deprecated, use libcap instead]) - dnl Linux requires the following for capset(), Android does not have it, - dnl but defines capset() in unistd.h instead. + # Linux requires the following for capset(), Android does not have it, + # but defines capset() in unistd.h instead. AC_CHECK_HEADERS([sys/capability.h]) AC_CHECK_FUNC(capset,,[AC_MSG_ERROR([capset() not found!])]) AC_DEFINE([CAPABILITIES_NATIVE], [], [have native linux capset()]) fi if test x$capabilities = xlibcap; then - AC_HAVE_LIBRARY([cap],[LIBS="$LIBS"],[AC_MSG_ERROR([libcap library not found])]) + AC_CHECK_LIB([cap],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([libcap library not found])],[]) AC_CHECK_HEADER([sys/capability.h], [AC_DEFINE([HAVE_SYS_CAPABILITY_H], [], [have sys/capability.h])], [AC_MSG_ERROR([libcap header sys/capability.h not found!])]) @@ -819,25 +856,29 @@ fi if test x$integrity_test = xtrue; then AC_MSG_CHECKING([for dladdr()]) - AC_TRY_COMPILE( - [#define _GNU_SOURCE - #include <dlfcn.h>], - [Dl_info info; dladdr(main, &info);], - [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]); + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#define _GNU_SOURCE + #include <dlfcn.h>]], + [[Dl_info info; dladdr(main, &info);]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]); AC_MSG_ERROR([dladdr() not supported, required by integrity-test!])] ) AC_MSG_CHECKING([for dl_iterate_phdr()]) - AC_TRY_COMPILE( - [#define _GNU_SOURCE - #include <link.h>], - [dl_iterate_phdr((void*)0, (void*)0);], - [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]); + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#define _GNU_SOURCE + #include <link.h>]], + [[dl_iterate_phdr((void*)0, (void*)0);]])], + [AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]); AC_MSG_ERROR([dl_iterate_phdr() not supported, required by integrity-test!])] ) fi if test x$bfd_backtraces = xtrue; then - AC_HAVE_LIBRARY([bfd],[LIBS="$LIBS"],[AC_MSG_ERROR([binutils libbfd not found!])]) + AC_CHECK_LIB([bfd],[main],[LIBS="$LIBS"],[AC_MSG_ERROR([binutils libbfd not found!])],[]) AC_CHECK_HEADER([bfd.h],[AC_DEFINE([HAVE_BFD_H],,[have binutils bfd.h])], [AC_MSG_ERROR([binutils bfd.h header not found!])]) BFDLIB="-lbfd" @@ -852,9 +893,9 @@ AC_SUBST(dev_headers) CFLAGS="$CFLAGS -include `pwd`/config.h" -dnl ============================================== -dnl collect plugin list for strongSwan components -dnl ============================================== +# =============================================== +# collect plugin list for strongSwan components +# =============================================== m4_include(m4/macros/add-plugin.m4) @@ -880,6 +921,7 @@ s_plugins= ADD_PLUGIN([test-vectors], [s charon openac scepclient pki]) ADD_PLUGIN([curl], [s charon scepclient scripts nm]) ADD_PLUGIN([soup], [s charon scripts nm]) +ADD_PLUGIN([unbound], [s charon scripts]) ADD_PLUGIN([ldap], [s charon scepclient scripts nm]) ADD_PLUGIN([mysql], [s charon pool manager medsrv attest]) ADD_PLUGIN([sqlite], [s charon pool manager medsrv attest]) @@ -903,6 +945,7 @@ ADD_PLUGIN([pkcs7], [s scepclient pki]) ADD_PLUGIN([pkcs8], [s charon openac scepclient pki scripts manager medsrv attest nm]) ADD_PLUGIN([pgp], [s charon]) ADD_PLUGIN([dnskey], [s charon]) +ADD_PLUGIN([ipseckey], [c charon]) ADD_PLUGIN([pem], [s charon openac scepclient pki scripts manager medsrv attest nm]) ADD_PLUGIN([padlock], [s charon]) ADD_PLUGIN([openssl], [s charon openac scepclient pki scripts manager medsrv attest nm]) @@ -964,13 +1007,14 @@ ADD_PLUGIN([tnccs-dynamic], [c charon]) ADD_PLUGIN([medsrv], [c charon]) ADD_PLUGIN([medcli], [c charon]) ADD_PLUGIN([dhcp], [c charon]) -ADD_PLUGIN([android], [c charon]) +ADD_PLUGIN([android-dns], [c charon]) ADD_PLUGIN([android-log], [c charon]) ADD_PLUGIN([ha], [c charon]) ADD_PLUGIN([whitelist], [c charon]) ADD_PLUGIN([lookip], [c charon]) ADD_PLUGIN([error-notify], [c charon]) ADD_PLUGIN([certexpire], [c charon]) +ADD_PLUGIN([systime-fix], [c charon]) ADD_PLUGIN([led], [c charon]) ADD_PLUGIN([duplicheck], [c charon]) ADD_PLUGIN([coupling], [c charon]) @@ -994,18 +1038,18 @@ AC_SUBST(medsrv_plugins) AC_SUBST(nm_plugins) AC_SUBST(c_plugins) -AC_SUBST(p_plugins) AC_SUBST(h_plugins) AC_SUBST(s_plugins) -dnl ========================= -dnl set Makefile.am vars -dnl ========================= +# ====================== +# set Makefile.am vars +# ====================== -dnl libstrongswan plugins -dnl ===================== +# libstrongswan plugins +# ----------------------- AM_CONDITIONAL(USE_TEST_VECTORS, test x$test_vectors = xtrue) AM_CONDITIONAL(USE_CURL, test x$curl = xtrue) +AM_CONDITIONAL(USE_UNBOUND, test x$unbound = xtrue) AM_CONDITIONAL(USE_SOUP, test x$soup = xtrue) AM_CONDITIONAL(USE_LDAP, test x$ldap = xtrue) AM_CONDITIONAL(USE_AES, test x$aes = xtrue) @@ -1045,17 +1089,18 @@ AM_CONDITIONAL(USE_CCM, test x$ccm = xtrue) AM_CONDITIONAL(USE_GCM, test x$gcm = xtrue) AM_CONDITIONAL(USE_AF_ALG, test x$af_alg = xtrue) -dnl charon plugins -dnl ============== +# charon plugins +# ---------------- AM_CONDITIONAL(USE_STROKE, test x$stroke = xtrue) AM_CONDITIONAL(USE_MEDSRV, test x$medsrv = xtrue) AM_CONDITIONAL(USE_MEDCLI, test x$medcli = xtrue) AM_CONDITIONAL(USE_UCI, test x$uci = xtrue) -AM_CONDITIONAL(USE_ANDROID, test x$android = xtrue) +AM_CONDITIONAL(USE_ANDROID_DNS, test x$android_dns = xtrue) AM_CONDITIONAL(USE_ANDROID_LOG, test x$android_log = xtrue) AM_CONDITIONAL(USE_MAEMO, test x$maemo = xtrue) AM_CONDITIONAL(USE_SMP, test x$smp = xtrue) AM_CONDITIONAL(USE_SQL, test x$sql = xtrue) +AM_CONDITIONAL(USE_IPSECKEY, test x$ipseckey = xtrue) AM_CONDITIONAL(USE_UPDOWN, test x$updown = xtrue) AM_CONDITIONAL(USE_DHCP, test x$dhcp = xtrue) AM_CONDITIONAL(USE_UNIT_TESTS, test x$unit_tester = xtrue) @@ -1065,6 +1110,7 @@ AM_CONDITIONAL(USE_WHITELIST, test x$whitelist = xtrue) AM_CONDITIONAL(USE_LOOKIP, test x$lookip = xtrue) AM_CONDITIONAL(USE_ERROR_NOTIFY, test x$error_notify = xtrue) AM_CONDITIONAL(USE_CERTEXPIRE, test x$certexpire = xtrue) +AM_CONDITIONAL(USE_SYSTIME_FIX, test x$systime_fix = xtrue) AM_CONDITIONAL(USE_LED, test x$led = xtrue) AM_CONDITIONAL(USE_DUPLICHECK, test x$duplicheck = xtrue) AM_CONDITIONAL(USE_COUPLING, test x$coupling = xtrue) @@ -1112,8 +1158,8 @@ AM_CONDITIONAL(USE_FARP, test x$farp = xtrue) AM_CONDITIONAL(USE_ADDRBLOCK, test x$addrblock = xtrue) AM_CONDITIONAL(USE_UNITY, test x$unity = xtrue) -dnl hydra plugins -dnl ============= +# hydra plugins +# --------------- AM_CONDITIONAL(USE_ATTR, test x$attr = xtrue) AM_CONDITIONAL(USE_ATTR_SQL, test x$attr_sql = xtrue -o x$sql = xtrue) AM_CONDITIONAL(USE_KERNEL_KLIPS, test x$kernel_klips = xtrue) @@ -1122,8 +1168,8 @@ AM_CONDITIONAL(USE_KERNEL_PFKEY, test x$kernel_pfkey = xtrue) AM_CONDITIONAL(USE_KERNEL_PFROUTE, test x$kernel_pfroute = xtrue) AM_CONDITIONAL(USE_RESOLVE, test x$resolve = xtrue) -dnl other options -dnl ============= +# other options +# --------------- AM_CONDITIONAL(USE_LEAK_DETECTIVE, test x$leak_detective = xtrue) AM_CONDITIONAL(USE_LOCK_PROFILER, test x$lock_profiler = xtrue) AM_CONDITIONAL(USE_DUMM, test x$dumm = xtrue) @@ -1147,6 +1193,7 @@ AM_CONDITIONAL(USE_LIBCHARON, test x$charon = xtrue -o x$conftest = xtrue -o x$n AM_CONDITIONAL(USE_LIBIPSEC, test x$libipsec = xtrue) AM_CONDITIONAL(USE_LIBTNCIF, test x$tnc_tnccs = xtrue -o x$imcv = xtrue) AM_CONDITIONAL(USE_LIBTNCCS, test x$tnc_tnccs = xtrue) +AM_CONDITIONAL(USE_LIBPTTLS, test x$tnc_tnccs = xtrue) AM_CONDITIONAL(USE_FILE_CONFIG, test x$stroke = xtrue) AM_CONDITIONAL(USE_IPSEC_SCRIPT, test x$stroke = xtrue -o x$tools = xtrue -o x$conftest = xtrue) AM_CONDITIONAL(USE_LIBCAP, test x$capabilities = xlibcap) @@ -1159,9 +1206,9 @@ AM_CONDITIONAL(USE_PTS, test x$pts = xtrue) AM_CONDITIONAL(USE_TROUSERS, test x$tss = xtrousers) AM_CONDITIONAL(MONOLITHIC, test x$monolithic = xtrue) -dnl ============================== -dnl set global definitions -dnl ============================== +# ======================== +# set global definitions +# ======================== if test x$mediation = xtrue; then AC_DEFINE([ME], [], [mediation extension support]) @@ -1179,11 +1226,11 @@ if test x$ikev2 = xtrue; then AC_DEFINE([USE_IKEV2], [], [support for IKEv2 protocol]) fi -dnl ============================== -dnl build Makefiles -dnl ============================== +# ================= +# build Makefiles +# ================= -AC_OUTPUT( +AC_CONFIG_FILES([ Makefile man/Makefile init/Makefile @@ -1217,6 +1264,7 @@ AC_OUTPUT( src/libstrongswan/plugins/dnskey/Makefile src/libstrongswan/plugins/pem/Makefile src/libstrongswan/plugins/curl/Makefile + src/libstrongswan/plugins/unbound/Makefile src/libstrongswan/plugins/soup/Makefile src/libstrongswan/plugins/ldap/Makefile src/libstrongswan/plugins/mysql/Makefile @@ -1245,6 +1293,7 @@ AC_OUTPUT( src/libradius/Makefile src/libtncif/Makefile src/libtnccs/Makefile + src/libpttls/Makefile src/libpts/Makefile src/libpts/plugins/imc_attestation/Makefile src/libpts/plugins/imv_attestation/Makefile @@ -1292,6 +1341,7 @@ AC_OUTPUT( src/libcharon/plugins/farp/Makefile src/libcharon/plugins/smp/Makefile src/libcharon/plugins/sql/Makefile + src/libcharon/plugins/ipseckey/Makefile src/libcharon/plugins/medsrv/Makefile src/libcharon/plugins/medcli/Makefile src/libcharon/plugins/addrblock/Makefile @@ -1302,11 +1352,12 @@ AC_OUTPUT( src/libcharon/plugins/lookip/Makefile src/libcharon/plugins/error_notify/Makefile src/libcharon/plugins/certexpire/Makefile + src/libcharon/plugins/systime_fix/Makefile src/libcharon/plugins/led/Makefile src/libcharon/plugins/duplicheck/Makefile src/libcharon/plugins/coupling/Makefile src/libcharon/plugins/radattr/Makefile - src/libcharon/plugins/android/Makefile + src/libcharon/plugins/android_dns/Makefile src/libcharon/plugins/android_log/Makefile src/libcharon/plugins/maemo/Makefile src/libcharon/plugins/stroke/Makefile @@ -1332,4 +1383,18 @@ AC_OUTPUT( src/conftest/Makefile scripts/Makefile testing/Makefile -) +]) +AC_OUTPUT + +# ======================== +# report enabled plugins +# ======================== + +AC_MSG_RESULT([]) +AC_MSG_RESULT([ strongSwan will be built with the following plugins]) +AC_MSG_RESULT([-----------------------------------------------------]) + +AC_MSG_RESULT([libstrongswan:$s_plugins]) +AC_MSG_RESULT([libcharon: $c_plugins]) +AC_MSG_RESULT([libhydra: $h_plugins]) +AC_MSG_RESULT([]) diff --git a/m4/macros/enable-disable.m4 b/m4/macros/enable-disable.m4 index 3d423652f..2e4552068 100644 --- a/m4/macros/enable-disable.m4 +++ b/m4/macros/enable-disable.m4 @@ -20,6 +20,7 @@ AC_DEFUN([ARG_ENABL_SET], # ARG_DISBL_SET(option, help) # --------------------------- # Create a --disable-$1 option with helptext, set a variable $1 to true/false +# All $1 are collected in the variable $enabled_by_default AC_DEFUN([ARG_DISBL_SET], [AC_ARG_ENABLE( [$1], @@ -32,5 +33,6 @@ AC_DEFUN([ARG_DISBL_SET], fi], [patsubst([$1], [-], [_])=true patsubst([$1], [-], [_])_given=false] - )] + ) + enabled_by_default=${enabled_by_default}" patsubst([$1], [-], [_])"] ) diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in index 2766cc4ed..e778ab773 100644 --- a/man/ipsec.conf.5.in +++ b/man/ipsec.conf.5.in @@ -452,6 +452,11 @@ suites, the strict flag exclamation mark) can be used, e.g: .BR aes256-sha512-modp4096! .TP +.BR ikedscp " = " 000000 " | <DSCP field>" +Differentiated Services Field Codepoint to set on outgoing IKE packets sent +from this connection. The value is a six digit binary encoded string defining +the Codepoint to set, as defined in RFC 2474. +.TP .BR ikelifetime " = " 3h " | <time>" how long the keying channel of a connection (ISAKMP or IKE SA) should last before being renegotiated. Also see EXPIRY/REKEY below. @@ -613,6 +618,10 @@ connection. See ipsec.secrets(5) for details about smartcard definitions. is required only if selecting the certificate with .B leftid is not sufficient, for example if multiple certificates use the same subject. +.br +Multiple certificate paths or PKCS#11 backends can be specified in a comma +separated list. The daemon chooses the certificate based on the received +certificate requests if possible before enforcing the first. .TP .BR leftcert2 " = <path>" Same as @@ -737,6 +746,14 @@ can be used to the same effect, e.g. .B leftprotoport=udp/%any or .BR leftprotoport=%any/53 . + +The port value can alternatively take the value +.B %opaque +for RFC 4301 OPAQUE selectors, or a numerical range in the form +.BR 1024-65535 . +None of the kernel backends currently supports opaque or port ranges and uses +.B %any +for policy installation instead. .TP .BR leftrsasigkey " = <raw rsa public key> | <path to public key>" the left participant's public key for RSA signature authentication, in RFC 2537 diff --git a/man/strongswan.conf.5.in b/man/strongswan.conf.5.in index 2fafed62d..3d80d7602 100644 --- a/man/strongswan.conf.5.in +++ b/man/strongswan.conf.5.in @@ -569,6 +569,9 @@ Request peer authentication based on a client certificate .BR charon.plugins.ha.segment_count " [1]" .TP +.BR charon.plugins.ipseckey.enable " [no]" +Enable the fetching of IPSECKEY RRs from the DNS +.TP .BR charon.plugins.led.activity_led .TP @@ -776,6 +779,12 @@ File to read random bytes from, instead of @DEV_RANDOM@ .TP .BR libstrongswan.plugins.random.urandom " [@DEV_URANDOM@]" File to read pseudo random bytes from, instead of @DEV_URANDOM@ +.TP +.BR libstrongswan.plugins.unbound.resolv_conf " [/etc/resolv.conf]" +File to read DNS resolver configuration from +.TP +.BR libstrongswan.plugins.unbound.trust_anchors " [/etc/ipsec.d/dnssec.keys]" +File to read DNSSEC trust anchors from (usually root zone KSK) .SS libtnccs section .TP .BR libtnccs.tnc_config " [/etc/tnc_config]" @@ -1352,7 +1361,7 @@ Authentication method(s) the intiator uses Initiator ID used in load test .TP .BR charon.plugins.load-tester.initiator_match -Initiator ID to to match against as responder +Initiator ID to match against as responder .TP .BR charon.plugins.load-tester.initiator_tsi Traffic selector on initiator side, as proposed by initiator diff --git a/scripts/.gitignore b/scripts/.gitignore index 2c8b8008d..b97347fbd 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -11,3 +11,4 @@ crypt_burn hash_burn tls_test fetch +dnssec diff --git a/scripts/Makefile.am b/scripts/Makefile.am index ea399e84c..f7ecd9ef6 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -3,7 +3,8 @@ AM_CFLAGS = \ -DPLUGINS="\"${scripts_plugins}\"" noinst_PROGRAMS = bin2array bin2sql id2sql key2keyid keyid2sql oid2der \ - thread_analysis dh_speed pubkey_speed crypt_burn hash_burn fetch + thread_analysis dh_speed pubkey_speed crypt_burn hash_burn fetch \ + dnssec if USE_TLS noinst_PROGRAMS += tls_test @@ -24,6 +25,7 @@ pubkey_speed_SOURCES = pubkey_speed.c crypt_burn_SOURCES = crypt_burn.c hash_burn_SOURCES = hash_burn.c fetch_SOURCES = fetch.c +dnssec_SOURCES = dnssec.c id2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la key2keyid_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la keyid2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la @@ -33,6 +35,7 @@ pubkey_speed_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la -lrt crypt_burn_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la hash_burn_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la fetch_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la +dnssec_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la key2keyid.o : $(top_builddir)/config.status diff --git a/scripts/dnssec.c b/scripts/dnssec.c new file mode 100644 index 000000000..89ea56ea6 --- /dev/null +++ b/scripts/dnssec.c @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2011-2012 Reto Guadagnini + * 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 <stdio.h> + +#include <library.h> + +int main(int argc, char *argv[]) +{ + resolver_t *resolver; + resolver_response_t *response; + enumerator_t *enumerator; + rr_set_t *rrset; + rr_t *rr; + chunk_t chunk; + + library_init(NULL); + atexit(library_deinit); + if (!lib->plugins->load(lib->plugins, NULL, PLUGINS)) + { + return 1; + } + if (argc != 2) + { + fprintf(stderr, "usage: %s <name>\n", argv[0]); + return 1; + } + + resolver = lib->resolver->create(lib->resolver); + if (!resolver) + { + printf("failed to create a resolver!\n"); + return 1; + } + + response = resolver->query(resolver, argv[1], RR_CLASS_IN, RR_TYPE_A); + if (!response) + { + printf("no response received!\n"); + resolver->destroy(resolver); + return 1; + } + + printf("DNS response:\n"); + if (!response->has_data(response) || !response->query_name_exist(response)) + { + if (!response->has_data(response)) + { + printf(" no data in the response\n"); + } + if (!response->query_name_exist(response)) + { + printf(" query name does not exist\n"); + } + response->destroy(response); + resolver->destroy(resolver); + return 1; + } + + printf(" RRs in the response:\n"); + rrset = response->get_rr_set(response); + if (!rrset) + { + printf(" response contains no RRset!\n"); + response->destroy(response); + resolver->destroy(resolver); + return 1; + } + + enumerator = rrset->create_rr_enumerator(rrset); + while (enumerator->enumerate(enumerator, &rr)) + { + printf(" name: "); + printf(rr->get_name(rr)); + printf("\n"); + } + + enumerator = rrset->create_rrsig_enumerator(rrset); + if (enumerator) + { + printf(" RRSIGs for the RRset:\n"); + while (enumerator->enumerate(enumerator, &rr)) + { + printf(" name: "); + printf(rr->get_name(rr)); + printf("\n RDATA: "); + chunk = rr->get_rdata(rr); + chunk = chunk_to_hex(chunk, NULL, TRUE); + printf(chunk.ptr); + printf("\n"); + } + } + + printf(" security status of the response: "); + switch (response->get_security_state(response)) + { + case SECURE: + printf("SECURE\n\n"); + break; + case INSECURE: + printf("INSECURE\n\n"); + break; + case BOGUS: + printf("BOGUS\n\n"); + break; + case INDETERMINATE: + printf("INDETERMINATE\n\n"); + break; + } + response->destroy(response); + resolver->destroy(resolver); + return 0; +} diff --git a/src/Makefile.am b/src/Makefile.am index e4c0374a2..e71f73db3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -32,6 +32,10 @@ if USE_LIBTNCCS SUBDIRS += libtnccs endif +if USE_LIBPTTLS + SUBDIRS += libpttls +endif + if USE_IMCV SUBDIRS += libimcv endif diff --git a/src/charon-nm/nm/nm_service.c b/src/charon-nm/nm/nm_service.c index eb187496d..b96ab418b 100644 --- a/src/charon-nm/nm/nm_service.c +++ b/src/charon-nm/nm/nm_service.c @@ -501,7 +501,7 @@ static gboolean connect_(NMVPNPlugin *plugin, NMConnection *connection, ike_cfg = ike_cfg_create(IKEV2, TRUE, encap, "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), (char*)address, FALSE, IKEV2_UDP_PORT, - FRAGMENTATION_NO); + FRAGMENTATION_NO, 0); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); peer_cfg = peer_cfg_create(priv->name, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_REPLACE, 1, /* keyingtries */ @@ -718,4 +718,3 @@ NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds, } return plugin; } - diff --git a/src/charon/charon.c b/src/charon/charon.c index f4bd27d34..812b7620b 100644 --- a/src/charon/charon.c +++ b/src/charon/charon.c @@ -175,6 +175,7 @@ static void segv_handler(int signal) DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal); backtrace = backtrace_create(2); + backtrace->log(backtrace, NULL, TRUE); backtrace->log(backtrace, stderr, TRUE); backtrace->destroy(backtrace); diff --git a/src/conftest/config.c b/src/conftest/config.c index ae0d93460..7f05e9c72 100644 --- a/src/conftest/config.c +++ b/src/conftest/config.c @@ -107,7 +107,7 @@ static ike_cfg_t *load_ike_config(private_config_t *this, settings->get_int(settings, "configs.%s.lport", 500, config), settings->get_str(settings, "configs.%s.rhost", "%any", config), FALSE, settings->get_int(settings, "configs.%s.rport", 500, config), - FRAGMENTATION_NO); + FRAGMENTATION_NO, 0); token = settings->get_str(settings, "configs.%s.proposal", NULL, config); if (token) { @@ -188,7 +188,7 @@ static child_cfg_t *load_child_config(private_config_t *this, enumerator = enumerator_create_token(token, ",", " "); while (enumerator->enumerate(enumerator, &token)) { - ts = traffic_selector_create_from_cidr(token, 0, 0); + ts = traffic_selector_create_from_cidr(token, 0, 0, 65535); if (ts) { child_cfg->add_traffic_selector(child_cfg, TRUE, ts); @@ -212,7 +212,7 @@ static child_cfg_t *load_child_config(private_config_t *this, enumerator = enumerator_create_token(token, ",", " "); while (enumerator->enumerate(enumerator, &token)) { - ts = traffic_selector_create_from_cidr(token, 0, 0); + ts = traffic_selector_create_from_cidr(token, 0, 0, 65535); if (ts) { child_cfg->add_traffic_selector(child_cfg, FALSE, ts); diff --git a/src/conftest/config.h b/src/conftest/config.h index 2a62b9ce0..ce9e24586 100644 --- a/src/conftest/config.h +++ b/src/conftest/config.h @@ -14,7 +14,7 @@ */ /** - * @defgroup config config + * @defgroup config_t config * @{ @ingroup conftest */ diff --git a/src/conftest/hooks/hook.h b/src/conftest/hooks/hook.h index 39a15f21b..b93711726 100644 --- a/src/conftest/hooks/hook.h +++ b/src/conftest/hooks/hook.h @@ -14,8 +14,8 @@ */ /** - * @defgroup hook hook - * @{ @ingroup hooks + * @defgroup hook_t hook + * @{ @ingroup conftest */ #ifndef HOOK_H_ diff --git a/src/frontends/android/AndroidManifest.xml b/src/frontends/android/AndroidManifest.xml index 71288c627..c0ac8c1bd 100644 --- a/src/frontends/android/AndroidManifest.xml +++ b/src/frontends/android/AndroidManifest.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2012 Tobias Brunner + Copyright (C) 2012-2013 Tobias Brunner Copyright (C) 2012 Giuliano Grassi Copyright (C) 2012 Ralf Sager Hochschule fuer Technik Rapperswil @@ -17,8 +17,8 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.strongswan.android" - android:versionCode="9" - android:versionName="1.2.1" > + android:versionCode="10" + android:versionName="1.2.2" > <uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" /> diff --git a/src/frontends/android/jni/libandroidbridge/backend/android_creds.h b/src/frontends/android/jni/libandroidbridge/backend/android_creds.h index a3ecddde4..918708f14 100644 --- a/src/frontends/android/jni/libandroidbridge/backend/android_creds.h +++ b/src/frontends/android/jni/libandroidbridge/backend/android_creds.h @@ -49,7 +49,7 @@ struct android_creds_t { /** * Load the user certificate and private key * - * @preturn loaded client certificate, NULL on failure + * @return loaded client certificate, NULL on failure */ certificate_t *(*load_user_certificate)(android_creds_t *this); diff --git a/src/frontends/android/jni/libandroidbridge/backend/android_service.c b/src/frontends/android/jni/libandroidbridge/backend/android_service.c index cce5ff0d4..76c139881 100644 --- a/src/frontends/android/jni/libandroidbridge/backend/android_service.c +++ b/src/frontends/android/jni/libandroidbridge/backend/android_service.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Tobias Brunner + * Copyright (C) 2010-2013 Tobias Brunner * Copyright (C) 2012 Giuliano Grassi * Copyright (C) 2012 Ralf Sager * Hochschule fuer Technik Rapperswil @@ -167,6 +167,10 @@ static job_requeue_t handle_plain(private_android_service_t *this) if (len < 0) { + if (errno == EBADF) + { /* the TUN device got closed just before calling select(), retry */ + return JOB_REQUEUE_FAIR; + } DBG1(DBG_DMN, "select on TUN device failed: %s", strerror(errno)); return JOB_REQUEUE_NONE; } @@ -452,9 +456,49 @@ METHOD(listener_t, ike_reestablish, bool, return TRUE; } +static void add_auth_cfg_eap(private_android_service_t *this, + peer_cfg_t *peer_cfg) +{ + identification_t *user; + auth_cfg_t *auth; + + auth = auth_cfg_create(); + auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP); + user = identification_create_from_string(this->username); + auth->add(auth, AUTH_RULE_IDENTITY, user); + + this->creds->add_username_password(this->creds, this->username, + this->password); + memwipe(this->password, strlen(this->password)); + peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE); +} + +static bool add_auth_cfg_cert(private_android_service_t *this, + peer_cfg_t *peer_cfg) +{ + certificate_t *cert; + identification_t *id; + auth_cfg_t *auth; + + cert = this->creds->load_user_certificate(this->creds); + if (!cert) + { + return FALSE; + } + + auth = auth_cfg_create(); + auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); + auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert); + + id = cert->get_subject(cert); + auth->add(auth, AUTH_RULE_IDENTITY, id->clone(id)); + peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE); + return TRUE; +} + static job_requeue_t initiate(private_android_service_t *this) { - identification_t *gateway, *user; + identification_t *gateway; ike_cfg_t *ike_cfg; peer_cfg_t *peer_cfg; child_cfg_t *child_cfg; @@ -472,7 +516,7 @@ static job_requeue_t initiate(private_android_service_t *this) ike_cfg = ike_cfg_create(IKEV2, TRUE, TRUE, "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), this->gateway, FALSE, IKEV2_UDP_PORT, - FRAGMENTATION_NO); + FRAGMENTATION_NO, 0); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); peer_cfg = peer_cfg_create("android", ike_cfg, CERT_SEND_IF_ASKED, @@ -485,38 +529,21 @@ static job_requeue_t initiate(private_android_service_t *this) peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0)); /* local auth config */ - if (streq("ikev2-eap", this->type)) - { - auth = auth_cfg_create(); - auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP); - user = identification_create_from_string(this->username); - auth->add(auth, AUTH_RULE_IDENTITY, user); - - this->creds->add_username_password(this->creds, this->username, - this->password); - memwipe(this->password, strlen(this->password)); - peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE); - } - else if (streq("ikev2-cert", this->type)) + if (streq("ikev2-cert", this->type) || + streq("ikev2-cert-eap", this->type)) { - certificate_t *cert; - identification_t *id; - - cert = this->creds->load_user_certificate(this->creds); - if (!cert) + if (!add_auth_cfg_cert(this, peer_cfg)) { peer_cfg->destroy(peer_cfg); charonservice->update_status(charonservice, CHARONSERVICE_GENERIC_ERROR); return JOB_REQUEUE_NONE; - } - auth = auth_cfg_create(); - auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); - auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert); - id = cert->get_subject(cert); - auth->add(auth, AUTH_RULE_IDENTITY, id->clone(id)); - peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE); + } + if (streq("ikev2-eap", this->type) || + streq("ikev2-cert-eap", this->type)) + { + add_auth_cfg_eap(this, peer_cfg); } /* remote auth config */ diff --git a/src/frontends/android/jni/libandroidbridge/kernel/android_ipsec.h b/src/frontends/android/jni/libandroidbridge/kernel/android_ipsec.h index 3a2e8343f..b68c8b2a9 100644 --- a/src/frontends/android/jni/libandroidbridge/kernel/android_ipsec.h +++ b/src/frontends/android/jni/libandroidbridge/kernel/android_ipsec.h @@ -16,7 +16,7 @@ /** * @defgroup kernel_android_ipsec kernel_android_ipsec - * @{ @ingroup kernel_android + * @{ @ingroup android_kernel */ #ifndef KERNEL_ANDROID_IPSEC_H_ diff --git a/src/frontends/android/jni/libandroidbridge/kernel/android_net.h b/src/frontends/android/jni/libandroidbridge/kernel/android_net.h index 470029fad..f0605390d 100644 --- a/src/frontends/android/jni/libandroidbridge/kernel/android_net.h +++ b/src/frontends/android/jni/libandroidbridge/kernel/android_net.h @@ -15,7 +15,7 @@ /** * @defgroup kernel_android_net kernel_android_net - * @{ @ingroup kernel_android + * @{ @ingroup android_kernel */ #ifndef KERNEL_ANDROID_NET_H_ diff --git a/src/frontends/android/jni/libandroidbridge/kernel/network_manager.h b/src/frontends/android/jni/libandroidbridge/kernel/network_manager.h index 2638b5aa0..da0106829 100644 --- a/src/frontends/android/jni/libandroidbridge/kernel/network_manager.h +++ b/src/frontends/android/jni/libandroidbridge/kernel/network_manager.h @@ -15,7 +15,7 @@ /** * @defgroup network_manager network_manager - * @{ @ingroup kernel_android + * @{ @ingroup android_kernel */ #ifndef NETWORK_MANAGER_H_ diff --git a/src/frontends/android/res/values-de/arrays.xml b/src/frontends/android/res/values-de/arrays.xml index efa4bcb03..d0117b202 100644 --- a/src/frontends/android/res/values-de/arrays.xml +++ b/src/frontends/android/res/values-de/arrays.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2012 Tobias Brunner + Copyright (C) 2012-2013 Tobias Brunner Hochschule fuer Technik Rapperswil This program is free software; you can redistribute it and/or modify it @@ -18,5 +18,6 @@ <string-array name="vpn_types"> <item>IKEv2 EAP (Benutzername/Passwort)</item> <item>IKEv2 Zertifikat</item> + <item>IKEv2 Zertifikat + EAP (Benutzername/Passwort)</item> </string-array> </resources>
\ No newline at end of file diff --git a/src/frontends/android/res/values-pl/arrays.xml b/src/frontends/android/res/values-pl/arrays.xml index 3e1af5f82..1b74b2e57 100644 --- a/src/frontends/android/res/values-pl/arrays.xml +++ b/src/frontends/android/res/values-pl/arrays.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2012 Tobias Brunner + Copyright (C) 2012-2013 Tobias Brunner Hochschule fuer Technik Rapperswil This program is free software; you can redistribute it and/or modify it @@ -18,5 +18,6 @@ <string-array name="vpn_types"> <item>IKEv2 EAP (użytkownik/hasło)</item> <item>IKEv2 certyfikat</item> + <item>IKEv2 certyfikat + EAP (użytkownik/hasło)</item> </string-array> </resources>
\ No newline at end of file diff --git a/src/frontends/android/res/values-ru/arrays.xml b/src/frontends/android/res/values-ru/arrays.xml index 48a7219cc..55144f294 100644 --- a/src/frontends/android/res/values-ru/arrays.xml +++ b/src/frontends/android/res/values-ru/arrays.xml @@ -16,6 +16,7 @@ <!-- the order here must match the enum entries in VpnType.java --> <string-array name="vpn_types"> <item>IKEv2 EAP (Логин/Пароль)</item> - <item>Сертификат IKEv2</item> + <item>IKEv2 Сертификат</item> + <item>IKEv2 Сертификат + EAP (Логин/Пароль)</item> </string-array> </resources> diff --git a/src/frontends/android/res/values-ua/arrays.xml b/src/frontends/android/res/values-ua/arrays.xml index bd4366405..490fea5e1 100644 --- a/src/frontends/android/res/values-ua/arrays.xml +++ b/src/frontends/android/res/values-ua/arrays.xml @@ -16,6 +16,7 @@ <!-- the order here must match the enum entries in VpnType.java --> <string-array name="vpn_types"> <item>IKEv2 EAP (Логін/Пароль)</item> - <item>Сертифікати IKEv2</item> + <item>IKEv2 Сертифікати</item> + <item>IKEv2 Сертифікати + EAP (Логін/Пароль)</item> </string-array> </resources> diff --git a/src/frontends/android/res/values/arrays.xml b/src/frontends/android/res/values/arrays.xml index 21576f22c..1ac4cc21d 100644 --- a/src/frontends/android/res/values/arrays.xml +++ b/src/frontends/android/res/values/arrays.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!-- - Copyright (C) 2012 Tobias Brunner + Copyright (C) 2012-2013 Tobias Brunner Hochschule fuer Technik Rapperswil This program is free software; you can redistribute it and/or modify it @@ -18,5 +18,6 @@ <string-array name="vpn_types"> <item>IKEv2 EAP (Username/Password)</item> <item>IKEv2 Certificate</item> + <item>IKEv2 Certificate + EAP (Username/Password)</item> </string-array> </resources>
\ No newline at end of file diff --git a/src/frontends/android/src/org/strongswan/android/data/VpnType.java b/src/frontends/android/src/org/strongswan/android/data/VpnType.java index 44a4fa6b4..47cc1cb02 100644 --- a/src/frontends/android/src/org/strongswan/android/data/VpnType.java +++ b/src/frontends/android/src/org/strongswan/android/data/VpnType.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Tobias Brunner + * Copyright (C) 2012-2013 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -19,7 +19,8 @@ public enum VpnType { /* the order here must match the items in R.array.vpn_types */ IKEV2_EAP("ikev2-eap", true, false), - IKEV2_CERT("ikev2-cert", false, true); + IKEV2_CERT("ikev2-cert", false, true), + IKEV2_CERT_EAP("ikev2-cert-eap", true, true); private String mIdentifier; private boolean mCertificate; diff --git a/src/libcharon/Android.mk b/src/libcharon/Android.mk index b2d6c3128..a9319088f 100644 --- a/src/libcharon/Android.mk +++ b/src/libcharon/Android.mk @@ -62,7 +62,7 @@ processing/jobs/start_action_job.c processing/jobs/start_action_job.h \ processing/jobs/roam_job.c processing/jobs/roam_job.h \ processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \ processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \ -sa/eap/eap_method.c sa/eap/eap_method.h \ +sa/eap/eap_method.c sa/eap/eap_method.h sa/eap/eap_inner_method.h \ sa/eap/eap_manager.c sa/eap/eap_manager.h \ sa/xauth/xauth_method.c sa/xauth/xauth_method.h \ sa/xauth/xauth_manager.c sa/xauth/xauth_manager.h \ @@ -125,9 +125,8 @@ processing/jobs/adopt_children_job.c processing/jobs/adopt_children_job.h # adding the plugin source files -LOCAL_SRC_FILES += $(call add_plugin, android) -ifneq ($(call plugin_enabled, android),) -LOCAL_C_INCLUDES += frameworks/base/cmds/keystore +LOCAL_SRC_FILES += $(call add_plugin, android-dns) +ifneq ($(call plugin_enabled, android-dns),) LOCAL_SHARED_LIBRARIES += libcutils endif diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 5203890ff..536bab473 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -60,7 +60,7 @@ processing/jobs/start_action_job.c processing/jobs/start_action_job.h \ processing/jobs/roam_job.c processing/jobs/roam_job.h \ processing/jobs/update_sa_job.c processing/jobs/update_sa_job.h \ processing/jobs/inactivity_job.c processing/jobs/inactivity_job.h \ -sa/eap/eap_method.c sa/eap/eap_method.h \ +sa/eap/eap_method.c sa/eap/eap_method.h sa/eap/eap_inner_method.h \ sa/eap/eap_manager.c sa/eap/eap_manager.h \ sa/xauth/xauth_method.c sa/xauth/xauth_method.h \ sa/xauth/xauth_manager.c sa/xauth/xauth_manager.h \ @@ -212,6 +212,13 @@ if MONOLITHIC endif endif +if USE_IPSECKEY + SUBDIRS += plugins/ipseckey +if MONOLITHIC + libcharon_la_LIBADD += plugins/ipseckey/libstrongswan-ipseckey.la +endif +endif + if USE_UPDOWN SUBDIRS += plugins/updown if MONOLITHIC @@ -450,10 +457,10 @@ if MONOLITHIC endif endif -if USE_ANDROID - SUBDIRS += plugins/android +if USE_ANDROID_DNS + SUBDIRS += plugins/android_dns if MONOLITHIC - libcharon_la_LIBADD += plugins/android/libstrongswan-android.la + libcharon_la_LIBADD += plugins/android_dns/libstrongswan-android-dns.la endif endif @@ -506,6 +513,13 @@ if MONOLITHIC endif endif +if USE_SYSTIME_FIX + SUBDIRS += plugins/systime_fix +if MONOLITHIC + libcharon_la_LIBADD += plugins/systime_fix/libstrongswan-systime-fix.la +endif +endif + if USE_LED SUBDIRS += plugins/led if MONOLITHIC diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c index 5e5fbba42..54a054e40 100644 --- a/src/libcharon/config/ike_cfg.c +++ b/src/libcharon/config/ike_cfg.c @@ -95,6 +95,11 @@ struct private_ike_cfg_t { fragmentation_t fragmentation; /** + * DSCP value to use on sent IKE packets + */ + u_int8_t dscp; + + /** * List of proposals to use */ linked_list_t *proposals; @@ -156,6 +161,12 @@ METHOD(ike_cfg_t, get_other_port, u_int16_t, return this->other_port; } +METHOD(ike_cfg_t, get_dscp, u_int8_t, + private_ike_cfg_t *this) +{ + return this->dscp; +} + METHOD(ike_cfg_t, add_proposal, void, private_ike_cfg_t *this, proposal_t *proposal) { @@ -312,7 +323,7 @@ METHOD(ike_cfg_t, destroy, void, ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap, char *me, bool my_allow_any, u_int16_t my_port, char *other, bool other_allow_any, u_int16_t other_port, - fragmentation_t fragmentation) + fragmentation_t fragmentation, u_int8_t dscp) { private_ike_cfg_t *this; @@ -326,6 +337,7 @@ ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap, .get_other_addr = _get_other_addr, .get_my_port = _get_my_port, .get_other_port = _get_other_port, + .get_dscp = _get_dscp, .add_proposal = _add_proposal, .get_proposals = _get_proposals, .select_proposal = _select_proposal, @@ -345,6 +357,7 @@ ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap, .other_allow_any = other_allow_any, .my_port = my_port, .other_port = other_port, + .dscp = dscp, .proposals = linked_list_create(), ); diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h index 5a7fae1e9..719ceb9dd 100644 --- a/src/libcharon/config/ike_cfg.h +++ b/src/libcharon/config/ike_cfg.h @@ -108,6 +108,13 @@ struct ike_cfg_t { u_int16_t (*get_other_port)(ike_cfg_t *this); /** + * Get the DSCP value to use for IKE packets send from connections. + * + * @return DSCP value + */ + u_int8_t (*get_dscp)(ike_cfg_t *this); + + /** * Adds a proposal to the list. * * The first added proposal has the highest priority, the last @@ -205,11 +212,12 @@ struct ike_cfg_t { * @param other_allow_any allow override of remote address by any address * @param other_port IKE port to use as dest, 500 uses IKEv2 port floating * @param fragmentation use IKEv1 fragmentation + * @param dscp DSCP value to send IKE packets with * @return ike_cfg_t object. */ ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap, char *me, bool my_allow_any, u_int16_t my_port, char *other, bool other_allow_any, u_int16_t other_port, - fragmentation_t fragmentation); + fragmentation_t fragmentation, u_int8_t dscp); #endif /** IKE_CFG_H_ @}*/ diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c index 28fdda735..ca964d749 100644 --- a/src/libcharon/encoding/message.c +++ b/src/libcharon/encoding/message.c @@ -151,7 +151,7 @@ static payload_rule_t ike_sa_init_r_rules[] = { {SECURITY_ASSOCIATION, 1, 1, FALSE, FALSE}, {KEY_EXCHANGE, 1, 1, FALSE, FALSE}, {NONCE, 1, 1, FALSE, FALSE}, - {CERTIFICATE_REQUEST, 0, 1, FALSE, FALSE}, + {CERTIFICATE_REQUEST, 0, MAX_CERTREQ_PAYLOADS, FALSE, FALSE}, {VENDOR_ID, 0, MAX_VID_PAYLOADS, FALSE, FALSE}, }; @@ -181,7 +181,7 @@ static payload_rule_t ike_auth_i_rules[] = { {AUTHENTICATION, 0, 1, TRUE, TRUE}, {ID_INITIATOR, 0, 1, TRUE, FALSE}, {CERTIFICATE, 0, MAX_CERT_PAYLOADS, TRUE, FALSE}, - {CERTIFICATE_REQUEST, 0, 1, TRUE, FALSE}, + {CERTIFICATE_REQUEST, 0, MAX_CERTREQ_PAYLOADS, TRUE, FALSE}, {ID_RESPONDER, 0, 1, TRUE, FALSE}, #ifdef ME {SECURITY_ASSOCIATION, 0, 1, TRUE, FALSE}, diff --git a/src/libcharon/encoding/payloads/notify_payload.c b/src/libcharon/encoding/payloads/notify_payload.c index d168e1c12..f7a13d728 100644 --- a/src/libcharon/encoding/payloads/notify_payload.c +++ b/src/libcharon/encoding/payloads/notify_payload.c @@ -65,7 +65,7 @@ ENUM_NEXT(notify_type_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_SA_NOT_ "ME_CONNECT_FAILED"); ENUM_NEXT(notify_type_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED, "MS_NOTIFY_STATUS"); -ENUM_NEXT(notify_type_names, INITIAL_CONTACT, PSK_CONFIRM, MS_NOTIFY_STATUS, +ENUM_NEXT(notify_type_names, INITIAL_CONTACT, ERX_SUPPORTED, MS_NOTIFY_STATUS, "INITIAL_CONTACT", "SET_WINDOW_SIZE", "ADDITIONAL_TS_POSSIBLE", @@ -108,8 +108,9 @@ ENUM_NEXT(notify_type_names, INITIAL_CONTACT, PSK_CONFIRM, MS_NOTIFY_STATUS, "IPSEC_REPLAY_COUNTER_SYNC", "SECURE PASSWORD_METHOD", "PSK_PERSIST", - "PSK_CONFIRM"); -ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, PSK_CONFIRM, + "PSK_CONFIRM", + "ERX_SUPPORTED"); +ENUM_NEXT(notify_type_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, ERX_SUPPORTED, "INITIAL_CONTACT"); ENUM_NEXT(notify_type_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1, "DPD_R_U_THERE", @@ -170,7 +171,7 @@ ENUM_NEXT(notify_type_short_names, ME_CONNECT_FAILED, ME_CONNECT_FAILED, CHILD_S "ME_CONN_FAIL"); ENUM_NEXT(notify_type_short_names, MS_NOTIFY_STATUS, MS_NOTIFY_STATUS, ME_CONNECT_FAILED, "MS_STATUS"); -ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, PSK_CONFIRM, MS_NOTIFY_STATUS, +ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, ERX_SUPPORTED, MS_NOTIFY_STATUS, "INIT_CONTACT", "SET_WINSIZE", "ADD_TS_POSS", @@ -213,8 +214,9 @@ ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT, PSK_CONFIRM, MS_NOTIFY_STATU "RPL_CTR_SYN", "SEC_PASSWD", "PSK_PST", - "PSK_CFM"); -ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, PSK_CONFIRM, + "PSK_CFM", + "ERX_SUP"); +ENUM_NEXT(notify_type_short_names, INITIAL_CONTACT_IKEV1, INITIAL_CONTACT_IKEV1, ERX_SUPPORTED, "INITIAL_CONTACT"); ENUM_NEXT(notify_type_short_names, DPD_R_U_THERE, DPD_R_U_THERE_ACK, INITIAL_CONTACT_IKEV1, "DPD", diff --git a/src/libcharon/encoding/payloads/notify_payload.h b/src/libcharon/encoding/payloads/notify_payload.h index 498c659b1..847fddc69 100644 --- a/src/libcharon/encoding/payloads/notify_payload.h +++ b/src/libcharon/encoding/payloads/notify_payload.h @@ -140,9 +140,11 @@ enum notify_type_t { IPSEC_REPLAY_COUNTER_SYNC = 16423, /* Secure password methods, RFC 6467 */ SECURE_PASSWORD_METHOD = 16424, - /* PACE - draft-kuegler-ipsecme-pace-ikev2 */ + /* PACE, RFC 6631 */ PSK_PERSIST = 16425, PSK_CONFIRM = 16426, + /* EAP Re-authentication Extension, RFC 6867 */ + ERX_SUPPORTED = 16427, /* IKEv1 initial contact */ INITIAL_CONTACT_IKEV1 = 24578, /* IKEv1 DPD */ diff --git a/src/libcharon/encoding/payloads/traffic_selector_substructure.c b/src/libcharon/encoding/payloads/traffic_selector_substructure.c index 15f791b95..334823db9 100644 --- a/src/libcharon/encoding/payloads/traffic_selector_substructure.c +++ b/src/libcharon/encoding/payloads/traffic_selector_substructure.c @@ -114,7 +114,11 @@ METHOD(payload_t, verify, status_t, { if (this->start_port > this->end_port) { - return FAILED; + /* OPAQUE ports are the only exception */ + if (this->start_port != 0xffff && this->end_port != 0) + { + return FAILED; + } } switch (this->ts_type) { diff --git a/src/libcharon/plugins/android/Makefile.am b/src/libcharon/plugins/android/Makefile.am deleted file mode 100644 index b10cd9527..000000000 --- a/src/libcharon/plugins/android/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ - -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ - -I$(top_srcdir)/src/libcharon - -AM_CFLAGS = -rdynamic - -if MONOLITHIC -noinst_LTLIBRARIES = libstrongswan-android.la -else -plugin_LTLIBRARIES = libstrongswan-android.la -endif - -libstrongswan_android_la_SOURCES = \ - android_plugin.c android_plugin.h \ - android_service.c android_service.h \ - android_handler.c android_handler.h \ - android_creds.c android_creds.h - -libstrongswan_android_la_LDFLAGS = -module -avoid-version -libstrongswan_android_la_LIBADD = -lcutils diff --git a/src/libcharon/plugins/android/android_creds.c b/src/libcharon/plugins/android/android_creds.c deleted file mode 100644 index 601c91e7b..000000000 --- a/src/libcharon/plugins/android/android_creds.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (C) 2010 Tobias Brunner - * 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 <keystore_get.h> - -#include "android_creds.h" - -#include <daemon.h> -#include <threading/rwlock.h> - -typedef struct private_android_creds_t private_android_creds_t; - -/** - * Private data of an android_creds_t object - */ -struct private_android_creds_t { - - /** - * Public interface - */ - android_creds_t public; - - /** - * List of trusted certificates, certificate_t* - */ - linked_list_t *certs; - - /** - * User name (ID) - */ - identification_t *user; - - /** - * User password - */ - char *pass; - - /** - * read/write lock - */ - rwlock_t *lock; - -}; - -/** - * Certificate enumerator data - */ -typedef struct { - private_android_creds_t *this; - key_type_t key; - identification_t *id; -} cert_data_t; - -/** - * Filter function for certificates enumerator - */ -static bool cert_filter(cert_data_t *data, certificate_t **in, - certificate_t **out) -{ - certificate_t *cert = *in; - public_key_t *public; - - public = cert->get_public_key(cert); - if (!public) - { - return FALSE; - } - if (data->key != KEY_ANY && public->get_type(public) != data->key) - { - public->destroy(public); - return FALSE; - } - if (data->id && data->id->get_type(data->id) == ID_KEY_ID && - public->has_fingerprint(public, data->id->get_encoding(data->id))) - { - public->destroy(public); - *out = cert; - return TRUE; - } - public->destroy(public); - if (data->id && !cert->has_subject(cert, data->id)) - { - return FALSE; - } - *out = cert; - return TRUE; -} - -/** - * Destroy certificate enumerator data - */ -static void cert_data_destroy(cert_data_t *this) -{ - this->this->lock->unlock(this->this->lock); - free(this); -} - -METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, - private_android_creds_t *this, certificate_type_t cert, key_type_t key, - identification_t *id, bool trusted) -{ - if (cert == CERT_X509 || cert == CERT_ANY) - { - cert_data_t *data; - this->lock->read_lock(this->lock); - INIT(data, .this = this, .id = id, .key = key); - return enumerator_create_filter( - this->certs->create_enumerator(this->certs), - (void*)cert_filter, data, (void*)cert_data_destroy); - } - return NULL; -} - -/** - * Shared key enumerator implementation - */ -typedef struct { - enumerator_t public; - private_android_creds_t *this; - shared_key_t *key; - bool done; -} shared_enumerator_t; - -METHOD(enumerator_t, shared_enumerate, bool, - shared_enumerator_t *this, shared_key_t **key, id_match_t *me, - id_match_t *other) -{ - if (this->done) - { - return FALSE; - } - *key = this->key; - *me = ID_MATCH_PERFECT; - *other = ID_MATCH_ANY; - this->done = TRUE; - return TRUE; -} - -METHOD(enumerator_t, shared_destroy, void, - shared_enumerator_t *this) -{ - this->key->destroy(this->key); - this->this->lock->unlock(this->this->lock); - free(this); -} - -METHOD(credential_set_t, create_shared_enumerator, enumerator_t*, - private_android_creds_t *this, shared_key_type_t type, - identification_t *me, identification_t *other) -{ - shared_enumerator_t *enumerator; - - this->lock->read_lock(this->lock); - - if (!this->user || !this->pass) - { - this->lock->unlock(this->lock); - return NULL; - } - if (type != SHARED_EAP && type != SHARED_IKE) - { - this->lock->unlock(this->lock); - return NULL; - } - if (me && !me->equals(me, this->user)) - { - this->lock->unlock(this->lock); - return NULL; - } - - INIT(enumerator, - .public = { - .enumerate = (void*)_shared_enumerate, - .destroy = _shared_destroy, - }, - .this = this, - .done = FALSE, - .key = shared_key_create(type, chunk_clone(chunk_create(this->pass, - strlen(this->pass)))), - ); - return &enumerator->public; -} - -METHOD(android_creds_t, add_certificate, bool, - private_android_creds_t *this, char *name) -{ - certificate_t *cert = NULL; - bool status = FALSE; - chunk_t chunk; -#ifdef KEYSTORE_MESSAGE_SIZE - /* most current interface, the eclair interface (without key length) is - * currently not supported */ - char value[KEYSTORE_MESSAGE_SIZE]; - chunk.ptr = value; - chunk.len = keystore_get(name, strlen(name), chunk.ptr); - if (chunk.len > 0) -#else - /* 1.6 interface, allocates memory */ - chunk.ptr = keystore_get(name, &chunk.len); - if (chunk.ptr) -#endif /* KEYSTORE_MESSAGE_SIZE */ - { - cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509, - BUILD_BLOB_PEM, chunk, BUILD_END); - if (cert) - { - this->lock->write_lock(this->lock); - this->certs->insert_last(this->certs, cert); - this->lock->unlock(this->lock); - status = TRUE; - } -#ifndef KEYSTORE_MESSAGE_SIZE - free(chunk.ptr); -#endif /* KEYSTORE_MESSAGE_SIZE */ - } - return status; -} - -METHOD(android_creds_t, set_username_password, void, - private_android_creds_t *this, identification_t *id, char *password) -{ - this->lock->write_lock(this->lock); - DESTROY_IF(this->user); - this->user = id->clone(id); - free(this->pass); - this->pass = strdupnull(password); - this->lock->unlock(this->lock); -} - -METHOD(android_creds_t, clear, void, - private_android_creds_t *this) -{ - certificate_t *cert; - this->lock->write_lock(this->lock); - while (this->certs->remove_last(this->certs, (void**)&cert) == SUCCESS) - { - cert->destroy(cert); - } - DESTROY_IF(this->user); - free(this->pass); - this->user = NULL; - this->pass = NULL; - this->lock->unlock(this->lock); -} - -METHOD(android_creds_t, destroy, void, - private_android_creds_t *this) -{ - clear(this); - this->certs->destroy(this->certs); - this->lock->destroy(this->lock); - free(this); -} - -/** - * Described in header. - */ -android_creds_t *android_creds_create() -{ - private_android_creds_t *this; - - INIT(this, - .public = { - .set = { - .create_cert_enumerator = _create_cert_enumerator, - .create_shared_enumerator = _create_shared_enumerator, - .create_private_enumerator = (void*)return_null, - .create_cdp_enumerator = (void*)return_null, - .cache_cert = (void*)nop, - }, - .add_certificate = _add_certificate, - .set_username_password = _set_username_password, - .clear = _clear, - .destroy = _destroy, - }, - .certs = linked_list_create(), - .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), - ); - - return &this->public; -} - diff --git a/src/libcharon/plugins/android/android_creds.h b/src/libcharon/plugins/android/android_creds.h deleted file mode 100644 index 0f7b8e0ea..000000000 --- a/src/libcharon/plugins/android/android_creds.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2010 Tobias Brunner - * 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 android_creds android_creds - * @{ @ingroup android - */ - -#ifndef ANDROID_CREDS_H_ -#define ANDROID_CREDS_H_ - -#include <credentials/credential_set.h> - -typedef struct android_creds_t android_creds_t; - -/** - * Android credentials helper. - */ -struct android_creds_t { - - /** - * Implements credential_set_t - */ - credential_set_t set; - - /** - * Add a trusted CA certificate from the Android keystore to serve by - * this set. - * - * @param name name/ID of the certificate in the keystore - * @return FALSE if the certificate does not exist or is invalid - */ - bool (*add_certificate)(android_creds_t *this, char *name); - - /** - * Set the username and password for authentication. - * - * @param id ID of the user - * @param password password to use for authentication - */ - void (*set_username_password)(android_creds_t *this, identification_t *id, - char *password); - - /** - * Clear the stored credentials. - */ - void (*clear)(android_creds_t *this); - - /** - * Destroy a android_creds instance. - */ - void (*destroy)(android_creds_t *this); - -}; - -/** - * Create an android_creds instance. - */ -android_creds_t *android_creds_create(); - -#endif /** ANDROID_CREDS_H_ @}*/ diff --git a/src/libcharon/plugins/android/android_service.c b/src/libcharon/plugins/android/android_service.c deleted file mode 100644 index 6af35e5df..000000000 --- a/src/libcharon/plugins/android/android_service.c +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (C) 2010 Tobias Brunner - * 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 <unistd.h> -#include <cutils/sockets.h> -#include <cutils/properties.h> -#include <signal.h> - -#include "android_service.h" - -#include <daemon.h> -#include <threading/thread.h> -#include <processing/jobs/callback_job.h> - -typedef struct private_android_service_t private_android_service_t; - -/** - * private data of Android service - */ -struct private_android_service_t { - - /** - * public interface - */ - android_service_t public; - - /** - * current IKE_SA - */ - ike_sa_t *ike_sa; - - /** - * android credentials - */ - android_creds_t *creds; - - /** - * android control socket - */ - int control; - -}; - -/** - * Some of the error codes defined in VpnManager.java - */ -typedef enum { - /** Error code to indicate an error from authentication. */ - VPN_ERROR_AUTH = 51, - /** Error code to indicate the connection attempt failed. */ - VPN_ERROR_CONNECTION_FAILED = 101, - /** Error code to indicate an error of remote server hanging up. */ - VPN_ERROR_REMOTE_HUNG_UP = 7, - /** Error code to indicate an error of losing connectivity. */ - VPN_ERROR_CONNECTION_LOST = 103, -} android_vpn_errors_t; - -/** - * send a status code back to the Android app - */ -static void send_status(private_android_service_t *this, u_char code) -{ - DBG1(DBG_CFG, "status of Android plugin changed: %d", code); - send(this->control, &code, 1, 0); -} - -METHOD(listener_t, ike_updown, bool, - private_android_service_t *this, ike_sa_t *ike_sa, bool up) -{ - /* this callback is only registered during initiation, so if the IKE_SA - * goes down we assume an authentication error */ - if (this->ike_sa == ike_sa && !up) - { - send_status(this, VPN_ERROR_AUTH); - return FALSE; - } - return TRUE; -} - -METHOD(listener_t, child_state_change, bool, - private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, - child_sa_state_t state) -{ - /* this callback is only registered during initiation, so we still have - * the control socket open */ - if (this->ike_sa == ike_sa && state == CHILD_DESTROYING) - { - send_status(this, VPN_ERROR_CONNECTION_FAILED); - return FALSE; - } - return TRUE; -} - -/** - * Callback used to shutdown the daemon - */ -static job_requeue_t shutdown_callback(void *data) -{ - kill(0, SIGTERM); - return JOB_REQUEUE_NONE; -} - -METHOD(listener_t, child_updown, bool, - private_android_service_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, - bool up) -{ - if (this->ike_sa == ike_sa) - { - if (up) - { - /* disable the hooks registered to catch initiation failures */ - this->public.listener.ike_updown = NULL; - this->public.listener.child_state_change = NULL; - property_set("vpn.status", "ok"); - } - else - { - callback_job_t *job; - /* the control socket is closed as soon as vpn.status is set to "ok" - * and the daemon proxy then only checks for terminated daemons to - * detect lost connections, so... */ - DBG1(DBG_CFG, "connection lost, raising delayed SIGTERM"); - /* to avoid any conflicts we send the SIGTERM not directly from this - * callback, but from a different thread. we also delay it to avoid - * a race condition during a regular shutdown */ - job = callback_job_create(shutdown_callback, NULL, NULL, NULL); - lib->scheduler->schedule_job(lib->scheduler, (job_t*)job, 1); - return FALSE; - } - } - return TRUE; -} - -METHOD(listener_t, ike_rekey, bool, - private_android_service_t *this, ike_sa_t *old, ike_sa_t *new) -{ - if (this->ike_sa == old) - { - this->ike_sa = new; - } - return TRUE; -} - -/** - * Read a string argument from the Android control socket - */ -static char *read_argument(int fd, u_char length) -{ - int offset = 0; - char *data = malloc(length + 1); - while (offset < length) - { - int n = recv(fd, &data[offset], length - offset, 0); - if (n < 0) - { - DBG1(DBG_CFG, "failed to read argument from Android" - " control socket: %s", strerror(errno)); - free(data); - return NULL; - } - offset += n; - } - data[length] = '\0'; - DBG3(DBG_CFG, "received argument from Android control socket: %s", data); - return data; -} - -/** - * handle the request received from the Android control socket - */ -static job_requeue_t initiate(private_android_service_t *this) -{ - bool oldstate; - int fd, i = 0; - char *hostname = NULL, *cacert = NULL, *username = NULL, *password = NULL; - identification_t *gateway = NULL, *user = NULL; - ike_cfg_t *ike_cfg; - peer_cfg_t *peer_cfg; - child_cfg_t *child_cfg; - traffic_selector_t *ts; - ike_sa_t *ike_sa; - auth_cfg_t *auth; - lifetime_cfg_t lifetime = { - .time = { - .life = 10800, /* 3h */ - .rekey = 10200, /* 2h50min */ - .jitter = 300 /* 5min */ - } - }; - - fd = accept(this->control, NULL, 0); - if (fd < 0) - { - DBG1(DBG_CFG, "accept on Android control socket failed: %s", - strerror(errno)); - return JOB_REQUEUE_NONE; - } - /* the original control socket is not used anymore */ - close(this->control); - this->control = fd; - - while (TRUE) - { - u_char length; - if (recv(fd, &length, 1, 0) != 1) - { - DBG1(DBG_CFG, "failed to read from Android control socket: %s", - strerror(errno)); - return JOB_REQUEUE_NONE; - } - - if (length == 0xFF) - { /* last argument */ - break; - } - else - { - switch (i++) - { - case 0: /* gateway */ - hostname = read_argument(fd, length); - break; - case 1: /* CA certificate name */ - cacert = read_argument(fd, length); - break; - case 2: /* username */ - username = read_argument(fd, length); - break; - case 3: /* password */ - password = read_argument(fd, length); - break; - } - } - } - - if (cacert) - { - if (!this->creds->add_certificate(this->creds, cacert)) - { - DBG1(DBG_CFG, "failed to load CA certificate"); - } - /* if this is a server cert we could use the cert subject as id - * but we have to test first if that possible to configure */ - } - - gateway = identification_create_from_string(hostname); - DBG1(DBG_CFG, "using CA certificate, gateway identitiy '%Y'", gateway); - - if (username) - { - user = identification_create_from_string(username); - this->creds->set_username_password(this->creds, user, password); - } - - ike_cfg = ike_cfg_create(IKEV2, TRUE, FALSE, "0.0.0.0", FALSE, - charon->socket->get_port(charon->socket, FALSE), - hostname, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO); - ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); - - peer_cfg = peer_cfg_create("android", ike_cfg, CERT_SEND_IF_ASKED, - UNIQUE_REPLACE, 1, /* keyingtries */ - 36000, 0, /* rekey 10h, reauth none */ - 600, 600, /* jitter, over 10min */ - TRUE, FALSE, /* mobike, aggressive */ - 0, 0, /* DPD delay, timeout */ - FALSE, NULL, NULL); /* mediation */ - peer_cfg->add_virtual_ip(peer_cfg, host_create_from_string("0.0.0.0", 0)); - - auth = auth_cfg_create(); - auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP); - auth->add(auth, AUTH_RULE_IDENTITY, user); - peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE); - auth = auth_cfg_create(); - auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY); - auth->add(auth, AUTH_RULE_IDENTITY, gateway); - peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE); - - child_cfg = child_cfg_create("android", &lifetime, NULL, TRUE, MODE_TUNNEL, - ACTION_NONE, ACTION_NONE, ACTION_NONE, FALSE, - 0, 0, NULL, NULL, 0); - child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP)); - ts = traffic_selector_create_dynamic(0, 0, 65535); - child_cfg->add_traffic_selector(child_cfg, TRUE, ts); - ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "0.0.0.0", - 0, "255.255.255.255", 65535); - child_cfg->add_traffic_selector(child_cfg, FALSE, ts); - peer_cfg->add_child_cfg(peer_cfg, child_cfg); - - /* get us an IKE_SA */ - ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager, - peer_cfg); - if (!ike_sa) - { - peer_cfg->destroy(peer_cfg); - send_status(this, VPN_ERROR_CONNECTION_FAILED); - return JOB_REQUEUE_NONE; - } - - if (!ike_sa->get_peer_cfg(ike_sa)) - { - ike_sa->set_peer_cfg(ike_sa, peer_cfg); - } - peer_cfg->destroy(peer_cfg); - - /* store the IKE_SA so we can track its progress */ - this->ike_sa = ike_sa; - - /* confirm that we received the request */ - send_status(this, i); - - /* get an additional reference because initiate consumes one */ - child_cfg->get_ref(child_cfg); - if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS) - { - DBG1(DBG_CFG, "failed to initiate tunnel"); - charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, - ike_sa); - send_status(this, VPN_ERROR_CONNECTION_FAILED); - return JOB_REQUEUE_NONE; - } - charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); - return JOB_REQUEUE_NONE; -} - -METHOD(android_service_t, destroy, void, - private_android_service_t *this) -{ - charon->bus->remove_listener(charon->bus, &this->public.listener); - close(this->control); - free(this); -} - -/** - * See header - */ -android_service_t *android_service_create(android_creds_t *creds) -{ - private_android_service_t *this; - - INIT(this, - .public = { - .listener = { - .ike_updown = _ike_updown, - .child_state_change = _child_state_change, - .child_updown = _child_updown, - .ike_rekey = _ike_rekey, - }, - .destroy = _destroy, - }, - .creds = creds, - ); - - this->control = android_get_control_socket("charon"); - if (this->control == -1) - { - DBG1(DBG_CFG, "failed to get Android control socket"); - free(this); - return NULL; - } - - if (listen(this->control, 1) < 0) - { - DBG1(DBG_CFG, "failed to listen on Android control socket: %s", - strerror(errno)); - close(this->control); - free(this); - return NULL; - } - - charon->bus->add_listener(charon->bus, &this->public.listener); - lib->processor->queue_job(lib->processor, - (job_t*)callback_job_create((callback_job_cb_t)initiate, this, - NULL, NULL)); - - return &this->public; -} - diff --git a/src/libcharon/plugins/android/android_service.h b/src/libcharon/plugins/android/android_service.h deleted file mode 100644 index d096d6cd5..000000000 --- a/src/libcharon/plugins/android/android_service.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2010 Tobias Brunner - * 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 android_service android_service - * @{ @ingroup android - */ - -#ifndef ANDROID_SERVICE_H_ -#define ANDROID_SERVICE_H_ - -typedef struct android_service_t android_service_t; - -#include <bus/listeners/listener.h> - -#include "android_creds.h" - -/** - * Service that interacts with the Android Settings frontend. - */ -struct android_service_t { - - /** - * Implements listener_t. - */ - listener_t listener; - - /** - * Destroy a android_service_t. - */ - void (*destroy)(android_service_t *this); - -}; - -/** - * Create an Android service instance. - * - * @param creds Android credentials - */ -android_service_t *android_service_create(android_creds_t *creds); - -#endif /** ANDROID_SERVICE_H_ @}*/ diff --git a/src/libcharon/plugins/android_dns/Makefile.am b/src/libcharon/plugins/android_dns/Makefile.am new file mode 100644 index 000000000..0d25f11d7 --- /dev/null +++ b/src/libcharon/plugins/android_dns/Makefile.am @@ -0,0 +1,18 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = -rdynamic + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-android-dns.la +else +plugin_LTLIBRARIES = libstrongswan-android-dns.la +endif + +libstrongswan_android_dns_la_SOURCES = \ + android_dns_plugin.c android_dns_plugin.h \ + android_dns_handler.c android_dns_handler.h + +libstrongswan_android_dns_la_LDFLAGS = -module -avoid-version +libstrongswan_android_dns_la_LIBADD = -lcutils
\ No newline at end of file diff --git a/src/libcharon/plugins/android/android_handler.c b/src/libcharon/plugins/android_dns/android_dns_handler.c index 29dbbbfd0..526810355 100644 --- a/src/libcharon/plugins/android/android_handler.c +++ b/src/libcharon/plugins/android_dns/android_dns_handler.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Tobias Brunner + * Copyright (C) 2010-2013 Tobias Brunner * Copyright (C) 2010 Martin Willi * Hochschule fuer Technik Rapperswil * @@ -14,41 +14,35 @@ * for more details. */ -#include "android_handler.h" +#include "android_dns_handler.h" #include <networking/host.h> #include <collections/linked_list.h> #include <cutils/properties.h> -typedef struct private_android_handler_t private_android_handler_t; +typedef struct private_android_dns_handler_t private_android_dns_handler_t; /** - * Private data of an android_handler_t object. + * Private data of an android_dns_handler_t object. */ -struct private_android_handler_t { +struct private_android_dns_handler_t { /** - * Public android_handler_t interface. + * Public interface */ - android_handler_t public; + android_dns_handler_t public; /** * List of registered DNS servers */ linked_list_t *dns; - - /** - * Whether the VPN frontend is used - */ - bool frontend; }; /** - * Prefixes to be used when installing DNS servers + * Prefix to be used when installing DNS servers */ #define DNS_PREFIX_DEFAULT "net" -#define DNS_PREFIX_FRONTEND "vpn" /** * Struct to store a pair of old and installed DNS servers @@ -63,7 +57,7 @@ typedef struct { /** * Destroy a pair of old and installed DNS servers */ -void destroy_dns_pair(dns_pair_t *this) +static void destroy_dns_pair(dns_pair_t *this) { DESTROY_IF(this->dns); DESTROY_IF(this->old); @@ -73,7 +67,7 @@ void destroy_dns_pair(dns_pair_t *this) /** * Filter pairs of DNS servers */ -bool filter_dns_pair(void *data, dns_pair_t **in, host_t **out) +static bool filter_dns_pair(void *data, dns_pair_t **in, host_t **out) { *out = (*in)->dns; return TRUE; @@ -82,11 +76,11 @@ bool filter_dns_pair(void *data, dns_pair_t **in, host_t **out) /** * Read DNS server property with a given index */ -host_t *get_dns_server(private_android_handler_t *this, int index) +static host_t *get_dns_server(private_android_dns_handler_t *this, int index) { host_t *dns = NULL; char key[10], value[PROPERTY_VALUE_MAX], - *prefix = this->frontend ? DNS_PREFIX_FRONTEND : DNS_PREFIX_DEFAULT; + *prefix = DNS_PREFIX_DEFAULT; if (snprintf(key, sizeof(key), "%s.dns%d", prefix, index) >= sizeof(key)) { @@ -103,10 +97,11 @@ host_t *get_dns_server(private_android_handler_t *this, int index) /** * Set DNS server property with a given index */ -bool set_dns_server(private_android_handler_t *this, int index, host_t *dns) +static bool set_dns_server(private_android_dns_handler_t *this, int index, + host_t *dns) { char key[10], value[PROPERTY_VALUE_MAX], - *prefix = this->frontend ? DNS_PREFIX_FRONTEND : DNS_PREFIX_DEFAULT; + *prefix = DNS_PREFIX_DEFAULT; if (snprintf(key, sizeof(key), "%s.dns%d", prefix, index) >= sizeof(key)) { @@ -133,7 +128,7 @@ bool set_dns_server(private_android_handler_t *this, int index, host_t *dns) } METHOD(attribute_handler_t, handle, bool, - private_android_handler_t *this, identification_t *id, + private_android_dns_handler_t *this, identification_t *id, configuration_attribute_type_t type, chunk_t data) { switch (type) @@ -163,7 +158,7 @@ METHOD(attribute_handler_t, handle, bool, } METHOD(attribute_handler_t, release, void, - private_android_handler_t *this, identification_t *server, + private_android_dns_handler_t *this, identification_t *server, configuration_attribute_type_t type, chunk_t data) { if (type == INTERNAL_IP4_DNS) @@ -197,7 +192,8 @@ METHOD(enumerator_t, enumerate_dns, bool, } METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *, - android_handler_t *this, identification_t *id, linked_list_t *vips) + private_android_dns_handler_t *this, identification_t *id, + linked_list_t *vips) { enumerator_t *enumerator; @@ -208,8 +204,8 @@ METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *, return enumerator; } -METHOD(android_handler_t, destroy, void, - private_android_handler_t *this) +METHOD(android_dns_handler_t, destroy, void, + private_android_dns_handler_t *this) { this->dns->destroy_function(this->dns, (void*)destroy_dns_pair); free(this); @@ -218,9 +214,9 @@ METHOD(android_handler_t, destroy, void, /** * See header */ -android_handler_t *android_handler_create(bool frontend) +android_dns_handler_t *android_dns_handler_create() { - private_android_handler_t *this; + private_android_dns_handler_t *this; INIT(this, .public = { @@ -232,7 +228,6 @@ android_handler_t *android_handler_create(bool frontend) .destroy = _destroy, }, .dns = linked_list_create(), - .frontend = frontend, ); return &this->public; diff --git a/src/libcharon/plugins/android/android_handler.h b/src/libcharon/plugins/android_dns/android_dns_handler.h index 0170958ee..d7b089dca 100644 --- a/src/libcharon/plugins/android/android_handler.h +++ b/src/libcharon/plugins/android_dns/android_dns_handler.h @@ -15,21 +15,21 @@ */ /** - * @defgroup android_handler android_handler - * @{ @ingroup android + * @defgroup android_dns_handler android_dns_handler + * @{ @ingroup android_dns */ -#ifndef ANDROID_HANDLER_H_ -#define ANDROID_HANDLER_H_ +#ifndef ANDROID_DNS_HANDLER_H_ +#define ANDROID_DNS_HANDLER_H_ #include <attributes/attribute_handler.h> -typedef struct android_handler_t android_handler_t; +typedef struct android_dns_handler_t android_dns_handler_t; /** * Android specific DNS attribute handler. */ -struct android_handler_t { +struct android_dns_handler_t { /** * Implements attribute_handler_t. @@ -37,16 +37,14 @@ struct android_handler_t { attribute_handler_t handler; /** - * Destroy a android_handler_t. + * Destroy a android_dns_handler_t. */ - void (*destroy)(android_handler_t *this); + void (*destroy)(android_dns_handler_t *this); }; /** - * Create a android_handler instance. - * - * @param frontend TRUE if the VPN frontend is used + * Create an android_dns_handler_t instance. */ -android_handler_t *android_handler_create(bool frontend); +android_dns_handler_t *android_dns_handler_create(); -#endif /** ANDROID_HANDLER_H_ @}*/ +#endif /** ANDROID_DNS_HANDLER_H_ @}*/ diff --git a/src/libcharon/plugins/android/android_plugin.c b/src/libcharon/plugins/android_dns/android_dns_plugin.c index c0f58e9b4..4e2b5f58b 100644 --- a/src/libcharon/plugins/android/android_plugin.c +++ b/src/libcharon/plugins/android_dns/android_dns_plugin.c @@ -1,6 +1,5 @@ /* - * Copyright (C) 2010 Tobias Brunner - * Copyright (C) 2010 Martin Willi + * Copyright (C) 2010-2013 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -14,66 +13,51 @@ * for more details. */ -#include "android_plugin.h" -#include "android_handler.h" -#include "android_creds.h" -#include "android_service.h" +#include "android_dns_plugin.h" +#include "android_dns_handler.h" #include <hydra.h> #include <daemon.h> -typedef struct private_android_plugin_t private_android_plugin_t; +typedef struct private_android_dns_plugin_t private_android_dns_plugin_t; /** - * Private data of an android_plugin_t object. + * Private data of an android_dns_plugin_t object. */ -struct private_android_plugin_t { +struct private_android_dns_plugin_t { /** - * Public android_plugin_t interface. + * Public interface */ - android_plugin_t public; + android_dns_plugin_t public; /** * Android specific DNS handler */ - android_handler_t *handler; - - /** - * Android specific credential set - */ - android_creds_t *creds; - - /** - * Service that interacts with the Android Settings frontend - */ - android_service_t *service; + android_dns_handler_t *handler; }; METHOD(plugin_t, get_name, char*, - private_android_plugin_t *this) + private_android_dns_plugin_t *this) { - return "android"; + return "android-dns"; } METHOD(plugin_t, destroy, void, - private_android_plugin_t *this) + private_android_dns_plugin_t *this) { hydra->attributes->remove_handler(hydra->attributes, &this->handler->handler); - lib->credmgr->remove_set(lib->credmgr, &this->creds->set); - this->creds->destroy(this->creds); this->handler->destroy(this->handler); - DESTROY_IF(this->service); free(this); } /** * See header */ -plugin_t *android_plugin_create() +plugin_t *android_dns_plugin_create() { - private_android_plugin_t *this; + private_android_dns_plugin_t *this; INIT(this, .public = { @@ -83,15 +67,10 @@ plugin_t *android_plugin_create() .destroy = _destroy, }, }, - .creds = android_creds_create(), + .handler = android_dns_handler_create(), ); - this->service = android_service_create(this->creds); - this->handler = android_handler_create(this->service != NULL); - - lib->credmgr->add_set(lib->credmgr, &this->creds->set); hydra->attributes->add_handler(hydra->attributes, &this->handler->handler); return &this->public.plugin; } - diff --git a/src/libcharon/plugins/android/android_plugin.h b/src/libcharon/plugins/android_dns/android_dns_plugin.h index 987f2aa37..e9e57dc24 100644 --- a/src/libcharon/plugins/android/android_plugin.h +++ b/src/libcharon/plugins/android_dns/android_dns_plugin.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Martin Willi + * Copyright (C) 2013 Tobias Brunner * Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -14,24 +14,24 @@ */ /** - * @defgroup android android + * @defgroup android_dns android_dns * @ingroup cplugins * - * @defgroup android_plugin android_plugin - * @{ @ingroup android + * @defgroup android_dns_plugin android_dns_plugin + * @{ @ingroup android_dns */ -#ifndef ANDROID_PLUGIN_H_ -#define ANDROID_PLUGIN_H_ +#ifndef ANDROID_DNS_PLUGIN_H_ +#define ANDROID_DNS_PLUGIN_H_ #include <plugins/plugin.h> -typedef struct android_plugin_t android_plugin_t; +typedef struct android_dns_plugin_t android_dns_plugin_t; /** - * Plugin providing functionality specific to the Android platform. + * Plugin providing an Android-specific handler for DNS servers. */ -struct android_plugin_t { +struct android_dns_plugin_t { /** * Implements plugin interface. @@ -39,4 +39,4 @@ struct android_plugin_t { plugin_t plugin; }; -#endif /** ANDROID_PLUGIN_H_ @}*/ +#endif /** ANDROID_DNS_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c index ffa1bae39..7363ade1d 100644 --- a/src/libcharon/plugins/eap_tnc/eap_tnc.c +++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -21,6 +21,8 @@ #include <utils/debug.h> #include <daemon.h> +#include <tncifimv.h> + /** * Maximum size of an EAP-TNC message */ @@ -44,15 +46,50 @@ struct private_eap_tnc_t { eap_tnc_t public; /** + * Outer EAP authentication type + */ + eap_type_t auth_type; + + /** * TLS stack, wrapped by EAP helper */ tls_eap_t *tls_eap; + + /** + * TNCCS instance running over EAP-TNC + */ + tnccs_t *tnccs; + }; METHOD(eap_method_t, initiate, status_t, private_eap_tnc_t *this, eap_payload_t **out) { chunk_t data; + u_int32_t auth_type; + + /* Determine TNC Client Authentication Type */ + switch (this->auth_type) + { + case EAP_TLS: + case EAP_TTLS: + case EAP_PEAP: + auth_type = TNC_AUTH_CERT; + break; + case EAP_MD5: + case EAP_MSCHAPV2: + case EAP_GTC: + case EAP_OTP: + auth_type = TNC_AUTH_PASSWORD; + break; + case EAP_SIM: + case EAP_AKA: + auth_type = TNC_AUTH_SIM; + break; + default: + auth_type = TNC_AUTH_UNKNOWN; + } + this->tnccs->set_auth_type(this->tnccs, auth_type); if (this->tls_eap->initiate(this->tls_eap, &data) == NEED_MORE) { @@ -122,6 +159,18 @@ METHOD(eap_method_t, destroy, void, free(this); } +METHOD(eap_inner_method_t, get_auth_type, eap_type_t, + private_eap_tnc_t *this) +{ + return this->auth_type; +} + +METHOD(eap_inner_method_t, set_auth_type, void, + private_eap_tnc_t *this, eap_type_t type) +{ + this->auth_type = type; +} + /** * Generic private constructor */ @@ -132,19 +181,22 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, int max_msg_count; char* protocol; tnccs_type_t type; - tnccs_t *tnccs; INIT(this, .public = { - .eap_method = { - .initiate = _initiate, - .process = _process, - .get_type = _get_type, - .is_mutual = _is_mutual, - .get_msk = _get_msk, - .get_identifier = _get_identifier, - .set_identifier = _set_identifier, - .destroy = _destroy, + .eap_inner_method = { + .eap_method = { + .initiate = _initiate, + .process = _process, + .get_type = _get_type, + .is_mutual = _is_mutual, + .get_msk = _get_msk, + .get_identifier = _get_identifier, + .set_identifier = _set_identifier, + .destroy = _destroy, + }, + .get_auth_type = _get_auth_type, + .set_auth_type = _set_auth_type, }, }, ); @@ -172,10 +224,11 @@ static eap_tnc_t *eap_tnc_create(identification_t *server, free(this); return NULL; } - tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, is_server); - this->tls_eap = tls_eap_create(EAP_TNC, (tls_t*)tnccs, - EAP_TNC_MAX_MESSAGE_LEN, - max_msg_count, FALSE); + this->tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, is_server, + server, peer, TNC_IFT_EAP_1_1); + this->tls_eap = tls_eap_create(EAP_TNC, &this->tnccs->tls, + EAP_TNC_MAX_MESSAGE_LEN, + max_msg_count, FALSE); if (!this->tls_eap) { free(this); diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.h b/src/libcharon/plugins/eap_tnc/eap_tnc.h index 09abe60fc..8c881f6cf 100644 --- a/src/libcharon/plugins/eap_tnc/eap_tnc.h +++ b/src/libcharon/plugins/eap_tnc/eap_tnc.h @@ -23,7 +23,7 @@ typedef struct eap_tnc_t eap_tnc_t; -#include <sa/eap/eap_method.h> +#include <sa/eap/eap_inner_method.h> /** * Implementation of the eap_method_t interface using EAP-TNC. @@ -31,9 +31,9 @@ typedef struct eap_tnc_t eap_tnc_t; struct eap_tnc_t { /** - * Implemented eap_method_t interface. + * Implemented eap_inner_method_t interface. */ - eap_method_t eap_method; + eap_inner_method_t eap_inner_method; }; /** diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c index 464de17ba..eef8d6682 100644 --- a/src/libcharon/plugins/eap_ttls/eap_ttls_server.c +++ b/src/libcharon/plugins/eap_ttls/eap_ttls_server.c @@ -20,6 +20,7 @@ #include <daemon.h> #include <sa/eap/eap_method.h> +#include <sa/eap/eap_inner_method.h> typedef struct private_eap_ttls_server_t private_eap_ttls_server_t; @@ -108,8 +109,11 @@ static status_t start_phase2_auth(private_eap_ttls_server_t *this) /** * If configured, start EAP-TNC protocol */ -static status_t start_phase2_tnc(private_eap_ttls_server_t *this) +static status_t start_phase2_tnc(private_eap_ttls_server_t *this, + eap_type_t auth_type) { + eap_inner_method_t *inner_method; + if (this->start_phase2_tnc && lib->settings->get_bool(lib->settings, "%s.plugins.eap-ttls.phase2_tnc", FALSE, charon->name)) { @@ -121,6 +125,9 @@ static status_t start_phase2_tnc(private_eap_ttls_server_t *this) DBG1(DBG_IKE, "%N method not available", eap_type_names, EAP_TNC); return FAILED; } + inner_method = (eap_inner_method_t *)this->method; + inner_method->set_auth_type(inner_method, auth_type); + this->start_phase2_tnc = FALSE; if (this->method->initiate(this->method, &this->out) == NEED_MORE) { @@ -237,7 +244,7 @@ METHOD(tls_application_t, process, status_t, if (lib->settings->get_bool(lib->settings, "%s.plugins.eap-ttls.request_peer_auth", FALSE, charon->name)) { - return start_phase2_tnc(this); + return start_phase2_tnc(this, EAP_TLS); } else { @@ -265,7 +272,7 @@ METHOD(tls_application_t, process, status_t, this->method = NULL; /* continue phase2 with EAP-TNC? */ - return start_phase2_tnc(this); + return start_phase2_tnc(this, type); case NEED_MORE: break; case FAILED: diff --git a/src/libcharon/plugins/ha/ha_tunnel.c b/src/libcharon/plugins/ha/ha_tunnel.c index 130c86e48..e6a09a76e 100644 --- a/src/libcharon/plugins/ha/ha_tunnel.c +++ b/src/libcharon/plugins/ha/ha_tunnel.c @@ -205,7 +205,7 @@ static void setup_tunnel(private_ha_tunnel_t *this, /* create config and backend */ ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, local, FALSE, charon->socket->get_port(charon->socket, FALSE), - remote, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO); + remote, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); peer_cfg = peer_cfg_create("ha", ike_cfg, CERT_NEVER_SEND, UNIQUE_KEEP, 0, 86400, 0, 7200, 3600, FALSE, FALSE, 30, @@ -288,4 +288,3 @@ ha_tunnel_t *ha_tunnel_create(char *local, char *remote, char *secret) return &this->public; } - diff --git a/src/libcharon/plugins/ipseckey/Makefile.am b/src/libcharon/plugins/ipseckey/Makefile.am new file mode 100644 index 000000000..0614017a0 --- /dev/null +++ b/src/libcharon/plugins/ipseckey/Makefile.am @@ -0,0 +1,18 @@ + +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-ipseckey.la +else +plugin_LTLIBRARIES = libstrongswan-ipseckey.la +endif + +libstrongswan_ipseckey_la_SOURCES = \ + ipseckey_plugin.h ipseckey_plugin.c \ + ipseckey_cred.h ipseckey_cred.c \ + ipseckey.h ipseckey.c + +libstrongswan_ipseckey_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/ipseckey/ipseckey.c b/src/libcharon/plugins/ipseckey/ipseckey.c new file mode 100644 index 000000000..78ae2cc2a --- /dev/null +++ b/src/libcharon/plugins/ipseckey/ipseckey.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 "ipseckey.h" + +#include <library.h> +#include <utils/debug.h> +#include <bio/bio_reader.h> + +typedef struct private_ipseckey_t private_ipseckey_t; + +/** +* private data of the ipseckey +*/ +struct private_ipseckey_t { + + /** + * public functions + */ + ipseckey_t public; + + /** + * Precedence + */ + u_int8_t precedence; + + /** + * Gateway type + */ + u_int8_t gateway_type; + + /** + * Algorithm + */ + u_int8_t algorithm; + + /** + * Gateway + */ + chunk_t gateway; + + /** + * Public key + */ + chunk_t public_key; +}; + +METHOD(ipseckey_t, get_precedence, u_int8_t, + private_ipseckey_t *this) +{ + return this->precedence; +} + +METHOD(ipseckey_t, get_gateway_type, ipseckey_gw_type_t, + private_ipseckey_t *this) +{ + return this->gateway_type; +} + +METHOD(ipseckey_t, get_algorithm, ipseckey_algorithm_t, + private_ipseckey_t *this) +{ + return this->algorithm; +} + +METHOD(ipseckey_t, get_gateway, chunk_t, + private_ipseckey_t *this) +{ + return this->gateway; +} + +METHOD(ipseckey_t, get_public_key, chunk_t, + private_ipseckey_t *this) +{ + return this->public_key; +} + +METHOD(ipseckey_t, destroy, void, + private_ipseckey_t *this) +{ + chunk_free(&this->gateway); + chunk_free(&this->public_key); + free(this); +} + +/* + * See header + */ +ipseckey_t *ipseckey_create_frm_rr(rr_t *rr) +{ + private_ipseckey_t *this; + bio_reader_t *reader = NULL; + u_int8_t label; + chunk_t tmp; + + INIT(this, + .public = { + .get_precedence = _get_precedence, + .get_gateway_type = _get_gateway_type, + .get_algorithm = _get_algorithm, + .get_gateway = _get_gateway, + .get_public_key = _get_public_key, + .destroy = _destroy, + }, + ); + + if (rr->get_type(rr) != RR_TYPE_IPSECKEY) + { + DBG1(DBG_CFG, "unable to create an ipseckey out of an RR " + "whose type is not IPSECKEY"); + free(this); + return NULL; + } + + /** Parse the content (RDATA field) of the RR */ + reader = bio_reader_create(rr->get_rdata(rr)); + if (!reader->read_uint8(reader, &this->precedence) || + !reader->read_uint8(reader, &this->gateway_type) || + !reader->read_uint8(reader, &this->algorithm)) + { + DBG1(DBG_CFG, "ipseckey RR has a wrong format"); + reader->destroy(reader); + free(this); + } + + switch (this->gateway_type) + { + case IPSECKEY_GW_TP_NOT_PRESENT: + break; + + case IPSECKEY_GW_TP_IPV4: + if (!reader->read_data(reader, 4, &this->gateway)) + { + DBG1(DBG_CFG, "ipseckey gateway field does not contain an " + "IPv4 address as expected"); + reader->destroy(reader); + free(this); + return NULL; + } + this->gateway = chunk_clone(this->gateway); + break; + + case IPSECKEY_GW_TP_IPV6: + if (!reader->read_data(reader, 16, &this->gateway)) + { + DBG1(DBG_CFG, "ipseckey gateway field does not contain an " + "IPv6 address as expected"); + reader->destroy(reader); + free(this); + return NULL; + } + this->gateway = chunk_clone(this->gateway); + break; + + case IPSECKEY_GW_TP_WR_ENC_DNAME: + /** + * Uncompressed domain name as defined in RFC 1035 chapter 3. + * + * TODO: Currently we ignore wire encoded domain names. + * + */ + while (reader->read_uint8(reader, &label) && + label != 0 && label < 192) + { + if (!reader->read_data(reader, label, &tmp)) + { + DBG1(DBG_CFG, "wrong wire encoded domain name format " + "in ipseckey gateway field"); + reader->destroy(reader); + free(this); + return NULL; + } + } + break; + + default: + DBG1(DBG_CFG, "unable to parse ipseckey gateway field"); + reader->destroy(reader); + free(this); + return NULL; + } + + if (!reader->read_data(reader, reader->remaining(reader), + &this->public_key)) + { + DBG1(DBG_CFG, "failed to read ipseckey public key field"); + reader->destroy(reader); + chunk_free(&this->gateway); + free(this); + return NULL; + } + this->public_key = chunk_clone(this->public_key); + reader->destroy(reader); + return &this->public; +} + diff --git a/src/libcharon/plugins/ipseckey/ipseckey.h b/src/libcharon/plugins/ipseckey/ipseckey.h new file mode 100644 index 000000000..5885daeee --- /dev/null +++ b/src/libcharon/plugins/ipseckey/ipseckey.h @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 ipseckey_i ipseckey + * @{ @ingroup ipseckey + */ + +#ifndef IPSECKEY_H_ +#define IPSECKEY_H_ + +typedef struct ipseckey_t ipseckey_t; +typedef enum ipseckey_algorithm_t ipseckey_algorithm_t; +typedef enum ipseckey_gw_type_t ipseckey_gw_type_t; + +#include <library.h> + +/** + * IPSECKEY gateway types as defined in RFC 4025. + */ +enum ipseckey_gw_type_t { + /** No gateway is present */ + IPSECKEY_GW_TP_NOT_PRESENT = 0, + /** A 4-byte IPv4 address is present */ + IPSECKEY_GW_TP_IPV4 = 1, + /** A 16-byte IPv6 address is present */ + IPSECKEY_GW_TP_IPV6 = 2, + /** A wire-encoded domain name is present */ + IPSECKEY_GW_TP_WR_ENC_DNAME = 3, +}; + +/** + * IPSECKEY algorithms as defined in RFC 4025. + */ +enum ipseckey_algorithm_t { + /** No key present */ + IPSECKEY_ALGORITHM_NONE = 0, + /** DSA key */ + IPSECKEY_ALGORITHM_DSA = 1, + /** RSA key */ + IPSECKEY_ALGORITHM_RSA = 2, +}; + +/** + * An IPSECKEY. + * + * Represents an IPSECKEY as defined in RFC 4025: + * + * 0 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | precedence | gateway type | algorithm | gateway | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-------------+ + + * ~ gateway ~ + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | / + * / public key / + * / / + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-| + * + * + * Note: RFC 4025 defines that the algorithm field has a length of 7 bits. + * We use 8 bits instead, because the use of 7 bits is very uncommon + * in internet protocols and might be an error in RFC 4025 + * (also the BIND DNS server uses 8 bits for the algorithm field of the + * IPSECKEY resource records). + * + */ +struct ipseckey_t { + + /** + * Get the precedence of the IPSECKEY. + * + * @return precedence + */ + u_int8_t (*get_precedence)(ipseckey_t *this); + + /** + * Get the type of the gateway. + * + * The "gateway type" determines the format of the gateway field + * of the IPSECKEY. + * + * @return gateway type + */ + ipseckey_gw_type_t (*get_gateway_type)(ipseckey_t *this); + + /** + * Get the algorithm. + * + * The "algorithm" determines the format of the public key field + * of the IPSECKEY. + * + * @return algorithm + */ + ipseckey_algorithm_t (*get_algorithm)(ipseckey_t *this); + + /** + * Get the content of the gateway field as chunk. + * + * The content is in network byte order and its format depends on the + * gateway type. + * + * The data pointed by the chunk is still owned by the IPSECKEY. + * Clone it if necessary. + * + * @return gateway field as chunk + */ + chunk_t (*get_gateway)(ipseckey_t *this); + + /** + * Get the content of the public key field as chunk. + * + * The format of the public key depends on the algorithm type. + * + * The data pointed by the chunk is still owned by the IPSECKEY. + * Clone it if necessary. + * + * @return public key field as chunk + */ + chunk_t (*get_public_key)(ipseckey_t *this); + + /** + * Destroy the IPSECKEY. + */ + void (*destroy) (ipseckey_t *this); +}; + +/** + * Create an ipseckey instance out of a resource record. + * + * @param rr resource record which contains an IPSECKEY + * @return ipseckey, NULL on failure + */ +ipseckey_t *ipseckey_create_frm_rr(rr_t *rr); + +#endif /** IPSECKEY_H_ @}*/ diff --git a/src/libcharon/plugins/ipseckey/ipseckey_cred.c b/src/libcharon/plugins/ipseckey/ipseckey_cred.c new file mode 100644 index 000000000..e8722f12c --- /dev/null +++ b/src/libcharon/plugins/ipseckey/ipseckey_cred.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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. + */ +#define _GNU_SOURCE +#include <stdio.h> +#include <string.h> + +#include "ipseckey_cred.h" +#include "ipseckey.h" + +#include <bio/bio_reader.h> +#include <daemon.h> + +typedef struct private_ipseckey_cred_t private_ipseckey_cred_t; + +/** + * Private data of an ipseckey_cred_t object + */ +struct private_ipseckey_cred_t { + + /** + * Public part + */ + ipseckey_cred_t public; + + /** + * DNS resolver + */ + resolver_t *res; +}; + +/** + * enumerator over certificates + */ +typedef struct { + /** implements enumerator interface */ + enumerator_t public; + /** inner enumerator (enumerates IPSECKEY resource records) */ + enumerator_t *inner; + /** response of the DNS resolver which contains the IPSECKEYs */ + resolver_response_t *response; + /* IPSECKEYs are not valid before this point in time */ + time_t notBefore; + /* IPSECKEYs are not valid after this point in time */ + time_t notAfter; + /* identity to which the IPSECKEY belongs */ + identification_t *identity; +} cert_enumerator_t; + +METHOD(enumerator_t, cert_enumerator_enumerate, bool, + cert_enumerator_t *this, certificate_t **cert) +{ + rr_t *cur_rr = NULL; + ipseckey_t *cur_ipseckey = NULL; + chunk_t pub_key; + public_key_t * key = NULL; + bool supported_ipseckey_found = FALSE; + + /* Get the next supported IPSECKEY using the inner enumerator. */ + while (this->inner->enumerate(this->inner, &cur_rr) && + !supported_ipseckey_found) + { + supported_ipseckey_found = TRUE; + + cur_ipseckey = ipseckey_create_frm_rr(cur_rr); + + if (!cur_ipseckey) + { + DBG1(DBG_CFG, "failed to parse ipseckey - skipping this key"); + supported_ipseckey_found = FALSE; + } + + if (cur_ipseckey && + cur_ipseckey->get_algorithm(cur_ipseckey) != IPSECKEY_ALGORITHM_RSA) + { + DBG1(DBG_CFG, "unsupported ipseckey algorithm -skipping this key"); + cur_ipseckey->destroy(cur_ipseckey); + supported_ipseckey_found = FALSE; + } + } + + if (supported_ipseckey_found) + { + /* + * Wrap the key of the IPSECKEY in a certificate and return this + * certificate. + */ + pub_key = cur_ipseckey->get_public_key(cur_ipseckey); + + key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, + BUILD_BLOB_DNSKEY, pub_key, + BUILD_END); + + if (!key) + { + DBG1(DBG_CFG, "failed to create public key from ipseckey"); + cur_ipseckey->destroy(cur_ipseckey); + return FALSE; + } + + *cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, + CERT_TRUSTED_PUBKEY, + BUILD_PUBLIC_KEY, key, + BUILD_SUBJECT, this->identity, + BUILD_NOT_BEFORE_TIME, this->notBefore, + BUILD_NOT_AFTER_TIME, this->notAfter, + BUILD_END); + return TRUE; + } + + return FALSE; +} + +METHOD(enumerator_t, cert_enumerator_destroy, void, + cert_enumerator_t *this) +{ + this->inner->destroy(this->inner); + this->response->destroy(this->response); + free(this); +} + +METHOD(credential_set_t, create_cert_enumerator, enumerator_t*, + private_ipseckey_cred_t *this, certificate_type_t cert, key_type_t key, + identification_t *id, bool trusted) +{ + char *fqdn = NULL; + resolver_response_t *response = NULL; + rr_set_t *rrset = NULL; + enumerator_t *rrsig_enum = NULL; + rr_t *rrsig = NULL; + bio_reader_t *reader = NULL; + chunk_t ignore; + u_int32_t nBefore, nAfter; + cert_enumerator_t *e; + + if (id && id->get_type(id) == ID_FQDN) + { + /** Query the DNS for the required IPSECKEY RRs */ + + if (0 >= asprintf(&fqdn, "%Y", id)) + { + DBG1(DBG_CFG, "empty FQDN string"); + return enumerator_create_empty(); + } + + DBG1(DBG_CFG, "performing a DNS query for IPSECKEY RRs of '%s'", + fqdn); + response = this->res->query(this->res, fqdn, RR_CLASS_IN, + RR_TYPE_IPSECKEY); + if (!response) + { + DBG1(DBG_CFG, " query for IPSECKEY RRs failed"); + free(fqdn); + return enumerator_create_empty(); + } + + if (!response->has_data(response) || + !response->query_name_exist(response)) + { + DBG1(DBG_CFG, " unable to retrieve IPSECKEY RRs from the DNS"); + response->destroy(response); + free(fqdn); + return enumerator_create_empty(); + } + + if (!(response->get_security_state(response) == SECURE)) + { + DBG1(DBG_CFG, " DNSSEC state of IPSECKEY RRs is not secure"); + response->destroy(response); + free(fqdn); + return enumerator_create_empty(); + } + + free(fqdn); + + /** Determine the validity period of the retrieved IPSECKEYs + * + * We use the "Signature Inception" and "Signature Expiration" field + * of the first RRSIG RR to determine the validity period of the + * IPSECKEY RRs. TODO: Take multiple RRSIGs into account. + */ + rrset = response->get_rr_set(response); + rrsig_enum = rrset->create_rrsig_enumerator(rrset); + if (!rrsig_enum || !rrsig_enum->enumerate(rrsig_enum, &rrsig)) + { + DBG1(DBG_CFG, " unable to determine the validity period of " + "IPSECKEY RRs because no RRSIGs are present"); + DESTROY_IF(rrsig_enum); + response->destroy(response); + return enumerator_create_empty(); + } + + /** + * Parse the RRSIG for its validity period (RFC 4034) + */ + reader = bio_reader_create(rrsig->get_rdata(rrsig)); + reader->read_data(reader, 8, &ignore); + reader->read_uint32(reader, &nAfter); + reader->read_uint32(reader, &nBefore); + reader->destroy(reader); + + /*Create and return an iterator over the retrieved IPSECKEYs */ + INIT(e, + .public = { + .enumerate = (void*)_cert_enumerator_enumerate, + .destroy = _cert_enumerator_destroy, + }, + .inner = response->get_rr_set(response)->create_rr_enumerator( + response->get_rr_set(response)), + .response = response, + .notBefore = nBefore, + .notAfter = nAfter, + .identity = id, + ); + + return &e->public; + } + + + return enumerator_create_empty(); +} + +METHOD(ipseckey_cred_t, destroy, void, + private_ipseckey_cred_t *this) +{ + this->res->destroy(this->res); + free(this); +} + +/** + * Described in header. + */ +ipseckey_cred_t *ipseckey_cred_create(resolver_t *res) +{ + private_ipseckey_cred_t *this; + + INIT(this, + .public = { + .set = { + .create_private_enumerator = (void*)return_null, + .create_cert_enumerator = _create_cert_enumerator, + .create_shared_enumerator = (void*)return_null, + .create_cdp_enumerator = (void*)return_null, + .cache_cert = (void*)nop, + }, + .destroy = _destroy, + }, + .res = res, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/ipseckey/ipseckey_cred.h b/src/libcharon/plugins/ipseckey/ipseckey_cred.h new file mode 100644 index 000000000..440020f5d --- /dev/null +++ b/src/libcharon/plugins/ipseckey/ipseckey_cred.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 ipseckey_cred_i ipseckey_cred + * @{ @ingroup ipseckey + */ + +#ifndef IPSECKEY_CRED_H_ +#define IPSECKEY_CRED_H_ + +#include <credentials/credential_set.h> +#include <resolver/resolver.h> + +typedef struct ipseckey_cred_t ipseckey_cred_t; + +/** + * IPSECKEY credential set. + * + * The ipseckey credential set contains IPSECKEYs as certificates of type + * pubkey_cert_t. + */ +struct ipseckey_cred_t { + + /** + * Implements credential_set_t interface + */ + credential_set_t set; + + /** + * Destroy the ipseckey_cred. + */ + void (*destroy)(ipseckey_cred_t *this); +}; + +/** + * Create an ipseckey_cred instance which uses the given resolver + * to query the DNS for IPSECKEY resource records. + * + * @param res resolver to use + * @return credential set + */ +ipseckey_cred_t *ipseckey_cred_create(resolver_t *res); + +#endif /** IPSECKEY_CRED_H_ @}*/ diff --git a/src/libcharon/plugins/ipseckey/ipseckey_plugin.c b/src/libcharon/plugins/ipseckey/ipseckey_plugin.c new file mode 100644 index 000000000..6f0f10507 --- /dev/null +++ b/src/libcharon/plugins/ipseckey/ipseckey_plugin.c @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 "ipseckey_plugin.h" + +#include <daemon.h> +#include "ipseckey_cred.h" + +typedef struct private_ipseckey_plugin_t private_ipseckey_plugin_t; + + +/** + * private data of the ipseckey plugin + */ +struct private_ipseckey_plugin_t { + + /** + * implements plugin interface + */ + ipseckey_plugin_t public; + + /** + * DNS resolver instance + */ + resolver_t *res; + + /** + * credential set + */ + ipseckey_cred_t *cred; + + /** + * IPSECKEY based authentication enabled + */ + bool enabled; +}; + +METHOD(plugin_t, get_name, char*, + private_ipseckey_plugin_t *this) +{ + return "ipseckey"; +} + +METHOD(plugin_t, destroy, void, + private_ipseckey_plugin_t *this) +{ + if (this->enabled) + { + lib->credmgr->remove_set(lib->credmgr, &this->cred->set); + } + this->res->destroy(this->res); + DESTROY_IF(this->cred); + free(this); +} + +/* + * see header file + */ +plugin_t *ipseckey_plugin_create() +{ + private_ipseckey_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .res = lib->resolver->create(lib->resolver), + .enabled = lib->settings->get_bool(lib->settings, + "charon.plugins.ipseckey.enable", FALSE), + ); + + if (!this->res) + { + DBG1(DBG_CFG, "ipseckey_plugin: Failed to create" + "a DNS resolver instance"); + destroy(this); + return NULL; + } + + if (this->enabled) + { + this->cred = ipseckey_cred_create(this->res); + lib->credmgr->add_set(lib->credmgr, &this->cred->set); + } + + return &this->public.plugin; +} + diff --git a/src/libcharon/plugins/ipseckey/ipseckey_plugin.h b/src/libcharon/plugins/ipseckey/ipseckey_plugin.h new file mode 100644 index 000000000..95acc79dd --- /dev/null +++ b/src/libcharon/plugins/ipseckey/ipseckey_plugin.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 ipseckey ipseckey + * @ingroup cplugins + * + * @defgroup ipseckey_plugin ipseckey_plugin + * @{ @ingroup ipseckey + */ + +#ifndef IPSECKEY_PLUGIN_H_ +#define IPSECKEY_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct ipseckey_plugin_t ipseckey_plugin_t; + +/** + * IPSECKEY plugin + * + * The IPSECKEY plugin registers a credential set for IPSECKEYs. + * + * With this credential set it is possible to authenticate tunnel endpoints + * using IPSECKEY resource records which are retrieved from the DNS in a secure + * way (DNSSEC). + */ +struct ipseckey_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** IPSECKEY_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/load_tester/load_tester_config.c b/src/libcharon/plugins/load_tester/load_tester_config.c index c6288c5d9..744eda58f 100644 --- a/src/libcharon/plugins/load_tester/load_tester_config.c +++ b/src/libcharon/plugins/load_tester/load_tester_config.c @@ -205,31 +205,75 @@ static bool equals(host_t *a, host_t *b) */ static void load_addrs(private_load_tester_config_t *this) { - enumerator_t *enumerator; - host_t *net; + enumerator_t *enumerator, *tokens; + host_t *from, *to; int bits; - char *iface, *cidr; + char *iface, *token, *pos; mem_pool_t *pool; - this->prefix = lib->settings->get_int(lib->settings, "%s.plugins.load-tester.addrs_prefix", 16, charon->name); enumerator = lib->settings->create_key_value_enumerator(lib->settings, "%s.plugins.load-tester.addrs", charon->name); - while (enumerator->enumerate(enumerator, &iface, &cidr)) + while (enumerator->enumerate(enumerator, &iface, &token)) { - net = host_create_from_subnet(cidr, &bits); - if (net) - { - DBG1(DBG_CFG, "loaded load-tester addresses %s", cidr); - pool = mem_pool_create(iface, net, bits); - net->destroy(net); - this->pools->insert_last(this->pools, pool); - } - else + tokens = enumerator_create_token(token, ",", " "); + while (tokens->enumerate(tokens, &token)) { - DBG1(DBG_CFG, "parsing load-tester addresses %s failed", cidr); + pos = strchr(token, '-'); + if (pos) + { /* range */ + *(pos++) = '\0'; + /* trim whitespace */ + while (*pos == ' ') + { + pos++; + } + while (token[strlen(token) - 1] == ' ') + { + token[strlen(token) - 1] = '\0'; + } + from = host_create_from_string(token, 0); + to = host_create_from_string(pos, 0); + if (from && to) + { + pool = mem_pool_create_range(iface, from, to); + if (pool) + { + DBG1(DBG_CFG, "loaded load-tester address range " + "%H-%H on %s", from, to, iface); + this->pools->insert_last(this->pools, pool); + } + from->destroy(from); + to->destroy(to); + } + else + { + DBG1(DBG_CFG, "parsing load-tester address range %s-%s " + "failed, skipped", token, pos); + DESTROY_IF(from); + DESTROY_IF(to); + } + } + else + { /* subnet */ + from = host_create_from_subnet(token, &bits); + if (from) + { + DBG1(DBG_CFG, "loaded load-tester address pool %H/%d on %s", + from, bits, iface); + pool = mem_pool_create(iface, from, bits); + from->destroy(from); + this->pools->insert_last(this->pools, pool); + } + else + { + DBG1(DBG_CFG, "parsing load-tester address %s failed, " + "skipped", token); + } + } } + tokens->destroy(tokens); } enumerator->destroy(enumerator); } @@ -369,7 +413,7 @@ static void add_ts(char *string, child_cfg_t *cfg, bool local) if (string) { - ts = traffic_selector_create_from_cidr(string, 0, 0); + ts = traffic_selector_create_from_cidr(string, 0, 0, 65535); if (!ts) { DBG1(DBG_CFG, "parsing TS string '%s' failed", string); @@ -491,7 +535,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num) ike_cfg = ike_cfg_create(this->version, TRUE, FALSE, local, FALSE, this->port + num - 1, remote, FALSE, IKEV2_NATT_PORT, - FRAGMENTATION_NO); + FRAGMENTATION_NO, 0); } else { @@ -499,7 +543,7 @@ static peer_cfg_t* generate_config(private_load_tester_config_t *this, uint num) local, FALSE, charon->socket->get_port(charon->socket, FALSE), remote, FALSE, IKEV2_UDP_PORT, - FRAGMENTATION_NO); + FRAGMENTATION_NO, 0); } ike_cfg->add_proposal(ike_cfg, this->proposal->clone(this->proposal)); peer_cfg = peer_cfg_create("load-test", ike_cfg, diff --git a/src/libcharon/plugins/maemo/maemo_service.c b/src/libcharon/plugins/maemo/maemo_service.c index 806e4cd65..d7539c2da 100644 --- a/src/libcharon/plugins/maemo/maemo_service.c +++ b/src/libcharon/plugins/maemo/maemo_service.c @@ -325,7 +325,8 @@ static gboolean initiate_connection(private_maemo_service_t *this, ike_cfg = ike_cfg_create(IKEV2, TRUE, FALSE, "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), - hostname, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO); + hostname, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO, + 0); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); peer_cfg = peer_cfg_create(this->current, ike_cfg, @@ -524,4 +525,3 @@ maemo_service_t *maemo_service_create() return &this->public; } - diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c index 4be3dea02..2bff70307 100644 --- a/src/libcharon/plugins/medcli/medcli_config.c +++ b/src/libcharon/plugins/medcli/medcli_config.c @@ -63,7 +63,7 @@ static traffic_selector_t *ts_from_string(char *str) { traffic_selector_t *ts; - ts = traffic_selector_create_from_cidr(str, 0, 0); + ts = traffic_selector_create_from_cidr(str, 0, 0, 65535); if (ts) { return ts; @@ -105,7 +105,7 @@ METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*, ike_cfg = ike_cfg_create(IKEV2, FALSE, FALSE, "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), - address, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO); + address, FALSE, IKEV2_UDP_PORT, FRAGMENTATION_NO, 0); ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE)); med_cfg = peer_cfg_create( "mediation", ike_cfg, @@ -381,7 +381,7 @@ medcli_config_t *medcli_config_create(database_t *db) "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), "0.0.0.0", FALSE, IKEV2_UDP_PORT, - FRAGMENTATION_NO), + FRAGMENTATION_NO, 0), ); this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); @@ -389,4 +389,3 @@ medcli_config_t *medcli_config_create(database_t *db) return &this->public; } - diff --git a/src/libcharon/plugins/medsrv/medsrv_config.c b/src/libcharon/plugins/medsrv/medsrv_config.c index be14380ea..06339220a 100644 --- a/src/libcharon/plugins/medsrv/medsrv_config.c +++ b/src/libcharon/plugins/medsrv/medsrv_config.c @@ -143,10 +143,9 @@ medsrv_config_t *medsrv_config_create(database_t *db) "0.0.0.0", FALSE, charon->socket->get_port(charon->socket, FALSE), "0.0.0.0", FALSE, IKEV2_UDP_PORT, - FRAGMENTATION_NO), + FRAGMENTATION_NO, 0), ); this->ike->add_proposal(this->ike, proposal_create_default(PROTO_IKE)); return &this->public; } - diff --git a/src/libcharon/plugins/medsrv/medsrv_config.h b/src/libcharon/plugins/medsrv/medsrv_config.h index fc8b0e972..03a41a7ce 100644 --- a/src/libcharon/plugins/medsrv/medsrv_config.h +++ b/src/libcharon/plugins/medsrv/medsrv_config.h @@ -15,7 +15,7 @@ /** * @defgroup medsrv_config_i medsrv_config - * @{ @ingroup medsrv + * @{ @ingroup medsrv_p */ #ifndef MEDSRV_CONFIG_H_ diff --git a/src/libcharon/plugins/medsrv/medsrv_creds.h b/src/libcharon/plugins/medsrv/medsrv_creds.h index d08adf3bf..2079601af 100644 --- a/src/libcharon/plugins/medsrv/medsrv_creds.h +++ b/src/libcharon/plugins/medsrv/medsrv_creds.h @@ -15,7 +15,7 @@ /** * @defgroup medsrv_creds_i medsrv_creds - * @{ @ingroup medsrv + * @{ @ingroup medsrv_p */ #ifndef MEDSRV_CREDS_H_ diff --git a/src/libcharon/plugins/medsrv/medsrv_plugin.h b/src/libcharon/plugins/medsrv/medsrv_plugin.h index 8736822ee..179fa3b3a 100644 --- a/src/libcharon/plugins/medsrv/medsrv_plugin.h +++ b/src/libcharon/plugins/medsrv/medsrv_plugin.h @@ -14,11 +14,11 @@ */ /** - * @defgroup medsrv medsrv + * @defgroup medsrv_p medsrv * @ingroup cplugins * * @defgroup medsrv_plugin medsrv_plugin - * @{ @ingroup medsrv + * @{ @ingroup medsrv_p */ #ifndef MEDSRV_PLUGIN_H_ diff --git a/src/libcharon/plugins/socket_default/socket_default_socket.c b/src/libcharon/plugins/socket_default/socket_default_socket.c index 51432c960..c0b744a68 100644 --- a/src/libcharon/plugins/socket_default/socket_default_socket.c +++ b/src/libcharon/plugins/socket_default/socket_default_socket.c @@ -55,6 +55,9 @@ #ifndef SOL_IPV6 #define SOL_IPV6 IPPROTO_IPV6 #endif +#ifndef IPV6_TCLASS +#define IPV6_TCLASS 67 +#endif /* IPV6_RECVPKTINFO is defined in RFC 3542 which obsoletes RFC 2292 that * previously defined IPV6_PKTINFO */ @@ -113,6 +116,26 @@ struct private_socket_default_socket_t { int ipv6_natt; /** + * DSCP value set on IPv4 socket + */ + u_int8_t dscp4; + + /** + * DSCP value set on IPv4 socket for NAT-T (4500 or natt) + */ + u_int8_t dscp4_natt; + + /** + * DSCP value set on IPv6 socket (500 or port) + */ + u_int8_t dscp6; + + /** + * DSCP value set on IPv6 socket for NAT-T (4500 or natt) + */ + u_int8_t dscp6_natt; + + /** * Maximum packet size to receive */ int max_packet; @@ -310,6 +333,7 @@ METHOD(socket_t, sender, status_t, struct msghdr msg; struct cmsghdr *cmsg; struct iovec iov; + u_int8_t *dscp; src = packet->get_source(packet); dst = packet->get_destination(packet); @@ -322,24 +346,34 @@ METHOD(socket_t, sender, status_t, family = dst->get_family(dst); if (sport == 0 || sport == this->port) { - if (family == AF_INET) - { - skt = this->ipv4; - } - else + switch (family) { - skt = this->ipv6; + case AF_INET: + skt = this->ipv4; + dscp = &this->dscp4; + break; + case AF_INET6: + skt = this->ipv6; + dscp = &this->dscp6; + break; + default: + return FAILED; } } else if (sport == this->natt) { - if (family == AF_INET) - { - skt = this->ipv4_natt; - } - else + switch (family) { - skt = this->ipv6_natt; + case AF_INET: + skt = this->ipv4_natt; + dscp = &this->dscp4_natt; + break; + case AF_INET6: + skt = this->ipv6_natt; + dscp = &this->dscp6_natt; + break; + default: + return FAILED; } } else @@ -348,6 +382,43 @@ METHOD(socket_t, sender, status_t, return FAILED; } + /* setting DSCP values per-packet in a cmsg seems not to be supported + * on Linux. We instead setsockopt() before sending it, this should be + * safe as only a single thread calls send(). */ + if (*dscp != packet->get_dscp(packet)) + { + if (family == AF_INET) + { + u_int8_t ds4; + + ds4 = packet->get_dscp(packet) << 2; + if (setsockopt(skt, SOL_IP, IP_TOS, &ds4, sizeof(ds4)) == 0) + { + *dscp = packet->get_dscp(packet); + } + else + { + DBG1(DBG_NET, "unable to set IP_TOS on socket: %s", + strerror(errno)); + } + } + else + { + u_int ds6; + + ds6 = packet->get_dscp(packet) << 2; + if (setsockopt(skt, SOL_IPV6, IPV6_TCLASS, &ds6, sizeof(ds6)) == 0) + { + *dscp = packet->get_dscp(packet); + } + else + { + DBG1(DBG_NET, "unable to set IPV6_TCLASS on socket: %s", + strerror(errno)); + } + } + } + memset(&msg, 0, sizeof(struct msghdr)); msg.msg_name = dst->get_sockaddr(dst);; msg.msg_namelen = *dst->get_sockaddr_len(dst); @@ -433,22 +504,24 @@ static int open_socket(private_socket_default_socket_t *this, int family, u_int16_t *port) { int on = TRUE; - struct sockaddr_storage addr; + union { + struct sockaddr sockaddr; + struct sockaddr_in sin; + struct sockaddr_in6 sin6; + } addr; socklen_t addrlen; u_int sol, pktinfo = 0; int skt; memset(&addr, 0, sizeof(addr)); - addr.ss_family = family; + addr.sockaddr.sa_family = family; /* precalculate constants depending on address family */ switch (family) { case AF_INET: - { - struct sockaddr_in *sin = (struct sockaddr_in *)&addr; - htoun32(&sin->sin_addr.s_addr, INADDR_ANY); - htoun16(&sin->sin_port, *port); - addrlen = sizeof(struct sockaddr_in); + addr.sin.sin_addr.s_addr = htonl(INADDR_ANY); + addr.sin.sin_port = htons(*port); + addrlen = sizeof(addr.sin); sol = SOL_IP; #ifdef IP_PKTINFO pktinfo = IP_PKTINFO; @@ -456,17 +529,13 @@ static int open_socket(private_socket_default_socket_t *this, pktinfo = IP_RECVDSTADDR; #endif break; - } case AF_INET6: - { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr; - memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any)); - htoun16(&sin6->sin6_port, *port); - addrlen = sizeof(struct sockaddr_in6); + memcpy(&addr.sin6.sin6_addr, &in6addr_any, sizeof(in6addr_any)); + addr.sin6.sin6_port = htons(*port); + addrlen = sizeof(addr.sin6); sol = SOL_IPV6; pktinfo = IPV6_RECVPKTINFO; break; - } default: return 0; } @@ -485,7 +554,7 @@ static int open_socket(private_socket_default_socket_t *this, } /* bind the socket */ - if (bind(skt, (struct sockaddr *)&addr, addrlen) < 0) + if (bind(skt, &addr.sockaddr, addrlen) < 0) { DBG1(DBG_NET, "unable to bind socket: %s", strerror(errno)); close(skt); @@ -495,7 +564,7 @@ static int open_socket(private_socket_default_socket_t *this, /* retrieve randomly allocated port if needed */ if (*port == 0) { - if (getsockname(skt, (struct sockaddr *)&addr, &addrlen) < 0) + if (getsockname(skt, &addr.sockaddr, &addrlen) < 0) { DBG1(DBG_NET, "unable to determine port: %s", strerror(errno)); close(skt); @@ -504,17 +573,11 @@ static int open_socket(private_socket_default_socket_t *this, switch (family) { case AF_INET: - { - struct sockaddr_in *sin = (struct sockaddr_in *)&addr; - *port = untoh16(&sin->sin_port); + *port = ntohs(addr.sin.sin_port); break; - } case AF_INET6: - { - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr; - *port = untoh16(&sin6->sin6_port); + *port = ntohs(addr.sin6.sin6_port); break; - } } } @@ -642,4 +705,3 @@ socket_default_socket_t *socket_default_socket_create() return &this->public; } - diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c index 37bd86671..c3471a078 100644 --- a/src/libcharon/plugins/sql/sql_config.c +++ b/src/libcharon/plugins/sql/sql_config.c @@ -262,7 +262,7 @@ static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e, local, FALSE, charon->socket->get_port(charon->socket, FALSE), remote, FALSE, IKEV2_UDP_PORT, - FRAGMENTATION_NO); + FRAGMENTATION_NO, 0); add_ike_proposals(this, ike_cfg, id); return ike_cfg; } @@ -620,4 +620,3 @@ sql_config_t *sql_config_create(database_t *db) return &this->public; } - diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c index 9f6124dc9..5970e7cf3 100644 --- a/src/libcharon/plugins/stroke/stroke_config.c +++ b/src/libcharon/plugins/stroke/stroke_config.c @@ -234,7 +234,8 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg msg->add_conn.other.address, msg->add_conn.other.allow_any, msg->add_conn.other.ikeport, - msg->add_conn.fragmentation); + msg->add_conn.fragmentation, + msg->add_conn.ikedscp); add_proposals(this, msg->add_conn.algorithms.ike, ike_cfg, NULL); return ike_cfg; } @@ -447,25 +448,42 @@ static auth_cfg_t *build_auth_cfg(private_stroke_config_t *this, identity = identification_create_from_string(id); if (cert) { - certificate = this->cred->load_peer(this->cred, cert); - if (certificate) + enumerator_t *enumerator; + bool has_subject = FALSE; + certificate_t *first = NULL; + + enumerator = enumerator_create_token(cert, ",", " "); + while (enumerator->enumerate(enumerator, &cert)) { - if (local) - { - this->ca->check_for_hash_and_url(this->ca, certificate); - } - cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate); - if (identity->get_type(identity) == ID_ANY || - !certificate->has_subject(certificate, identity)) + certificate = this->cred->load_peer(this->cred, cert); + if (certificate) { - DBG1(DBG_CFG, " id '%Y' not confirmed by certificate, " - "defaulting to '%Y'", identity, - certificate->get_subject(certificate)); - identity->destroy(identity); - identity = certificate->get_subject(certificate); - identity = identity->clone(identity); + if (local) + { + this->ca->check_for_hash_and_url(this->ca, certificate); + } + cfg->add(cfg, AUTH_RULE_SUBJECT_CERT, certificate); + if (!first) + { + first = certificate; + } + if (identity->get_type(identity) != ID_ANY && + certificate->has_subject(certificate, identity)) + { + has_subject = TRUE; + } } } + enumerator->destroy(enumerator); + + if (first && !has_subject) + { + DBG1(DBG_CFG, " id '%Y' not confirmed by certificate, " + "defaulting to '%Y'", identity, first->get_subject(first)); + identity->destroy(identity); + identity = first->get_subject(first); + identity = identity->clone(identity); + } } if (identity->get_type(identity) != ID_ANY) { @@ -877,7 +895,7 @@ static void add_ts(private_stroke_config_t *this, if (end->tohost) { ts = traffic_selector_create_dynamic(end->protocol, - end->port ? end->port : 0, end->port ? end->port : 65535); + end->from_port, end->to_port); child_cfg->add_traffic_selector(child_cfg, local, ts); } else @@ -890,7 +908,7 @@ static void add_ts(private_stroke_config_t *this, if (net) { ts = traffic_selector_create_from_subnet(net, 0, end->protocol, - end->port); + end->from_port, end->to_port); child_cfg->add_traffic_selector(child_cfg, local, ts); } } @@ -902,8 +920,8 @@ static void add_ts(private_stroke_config_t *this, enumerator = enumerator_create_token(end->subnets, ",", " "); while (enumerator->enumerate(enumerator, &subnet)) { - ts = traffic_selector_create_from_cidr(subnet, - end->protocol, end->port); + ts = traffic_selector_create_from_cidr(subnet, end->protocol, + end->from_port, end->to_port); if (ts) { child_cfg->add_traffic_selector(child_cfg, local, ts); diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c index 2771f0146..e31616cf8 100644 --- a/src/libcharon/plugins/stroke/stroke_socket.c +++ b/src/libcharon/plugins/stroke/stroke_socket.c @@ -516,11 +516,18 @@ static void stroke_loglevel(private_stroke_socket_t *this, DBG1(DBG_CFG, "received stroke: loglevel %d for %s", msg->loglevel.level, msg->loglevel.type); - group = enum_from_name(debug_names, msg->loglevel.type); - if ((int)group < 0) + if (strcaseeq(msg->loglevel.type, "any")) { - fprintf(out, "invalid type (%s)!\n", msg->loglevel.type); - return; + group = DBG_ANY; + } + else + { + group = enum_from_name(debug_names, msg->loglevel.type); + if ((int)group < 0) + { + fprintf(out, "invalid type (%s)!\n", msg->loglevel.type); + return; + } } charon->set_level(charon, group, msg->loglevel.level); } diff --git a/src/libcharon/plugins/systime_fix/Makefile.am b/src/libcharon/plugins/systime_fix/Makefile.am new file mode 100644 index 000000000..a1f843db7 --- /dev/null +++ b/src/libcharon/plugins/systime_fix/Makefile.am @@ -0,0 +1,15 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libhydra \ + -I$(top_srcdir)/src/libcharon + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-systime-fix.la +else +plugin_LTLIBRARIES = libstrongswan-systime-fix.la +endif + +libstrongswan_systime_fix_la_SOURCES = \ + systime_fix_validator.h systime_fix_validator.c \ + systime_fix_plugin.h systime_fix_plugin.c + +libstrongswan_systime_fix_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/systime_fix/systime_fix_plugin.c b/src/libcharon/plugins/systime_fix/systime_fix_plugin.c new file mode 100644 index 000000000..7727ba03b --- /dev/null +++ b/src/libcharon/plugins/systime_fix/systime_fix_plugin.c @@ -0,0 +1,256 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * 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 "systime_fix_plugin.h" +#include "systime_fix_validator.h" + +#include <daemon.h> +#include <processing/jobs/callback_job.h> +#include <processing/jobs/delete_ike_sa_job.h> +#include <processing/jobs/rekey_ike_sa_job.h> + +#include <time.h> + +/** + * Defining _XOPEN_SOURCE is difficult with libstrongswan includes, + * declare function explicitly. + */ +char *strptime(const char *s, const char *format, struct tm *tm); + +typedef struct private_systime_fix_plugin_t private_systime_fix_plugin_t; + +/** + * Private data of systime_fix plugin + */ +struct private_systime_fix_plugin_t { + + /** + * Implements plugin interface + */ + systime_fix_plugin_t public; + + /** + * Certificate lifetime validator + */ + systime_fix_validator_t *validator; + + /** + * Interval we check for a now-valid system time, in seconds. 0 if disabled + */ + u_int interval; + + /** + * Timestamp where we start considering system time valid + */ + time_t threshold; + + /** + * Do we trigger reauth or delete when finding expired certificates? + */ + bool reauth; +}; + +METHOD(plugin_t, get_name, char*, + private_systime_fix_plugin_t *this) +{ + return "systime-fix"; +} + +METHOD(plugin_t, destroy, void, + private_systime_fix_plugin_t *this) +{ + if (this->validator) + { + lib->credmgr->remove_validator(lib->credmgr, &this->validator->validator); + this->validator->destroy(this->validator); + } + free(this); +} + +/** + * Check if all certificates associated to an IKE_SA have valid lifetimes + */ +static bool has_invalid_certs(ike_sa_t *ike_sa) +{ + enumerator_t *cfgs, *items; + certificate_t *cert; + auth_rule_t type; + auth_cfg_t *auth; + time_t not_before, not_after; + bool valid = TRUE; + + cfgs = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE); + while (valid && cfgs->enumerate(cfgs, &auth)) + { + items = auth->create_enumerator(auth); + while (valid && items->enumerate(items, &type, &cert)) + { + switch (type) + { + case AUTH_RULE_SUBJECT_CERT: + case AUTH_RULE_IM_CERT: + case AUTH_RULE_CA_CERT: + if (!cert->get_validity(cert, NULL, ¬_before, ¬_after)) + { + DBG1(DBG_CFG, "certificate '%Y' invalid " + "(valid from %T to %T)", cert->get_subject(cert), + ¬_before, FALSE, ¬_after, FALSE); + valid = FALSE; + } + break; + default: + break; + } + } + items->destroy(items); + } + cfgs->destroy(cfgs); + + if (valid) + { + DBG1(DBG_CFG, "all certificates have valid lifetimes"); + } + return !valid; +} + +/** + * Check system time, reevaluate certificates + */ +static job_requeue_t check_systime(private_systime_fix_plugin_t *this) +{ + enumerator_t *enumerator; + ike_sa_t *ike_sa; + char *action; + job_t *job; + + if (time(NULL) < this->threshold) + { + DBG2(DBG_CFG, "systime not valid, rechecking in %ds", this->interval); + lib->scheduler->schedule_job(lib->scheduler, (job_t*) + callback_job_create((callback_job_cb_t)check_systime, this, + NULL, NULL), this->interval); + return JOB_REQUEUE_NONE; + } + + DBG1(DBG_CFG, "system time got valid, rechecking certificates"); + + enumerator = charon->ike_sa_manager->create_enumerator( + charon->ike_sa_manager, TRUE); + while (enumerator->enumerate(enumerator, &ike_sa)) + { + if (has_invalid_certs(ike_sa)) + { + if (this->reauth) + { + action = "reauthenticating"; + job = &rekey_ike_sa_job_create(ike_sa->get_id(ike_sa), + TRUE)->job_interface; + } + else + { + action = "deleting"; + job = &delete_ike_sa_job_create(ike_sa->get_id(ike_sa), + TRUE)->job_interface; + } + DBG1(DBG_CFG, "%s[%d] has certificates not valid, %s IKE_SA", + ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa), + action); + lib->processor->queue_job(lib->processor, job); + } + } + enumerator->destroy(enumerator); + + return JOB_REQUEUE_NONE; +} + +/** + * Load cert lifetime validator configuration + */ +static bool load_validator(private_systime_fix_plugin_t *this) +{ + struct tm tm = { + .tm_mday = 1, + }; + char *str, *fmt; + + fmt = lib->settings->get_str(lib->settings, + "%s.plugins.%s.threshold_format", "%Y", charon->name, get_name(this)); + str = lib->settings->get_str(lib->settings, + "%s.plugins.%s.threshold", NULL, charon->name, get_name(this)); + if (!str) + { + DBG1(DBG_CFG, "no threshold configured for %s, disabled", + get_name(this)); + return FALSE; + } + if (strptime(str, fmt, &tm) == NULL) + { + DBG1(DBG_CFG, "threshold for %s invalid, disabled", get_name(this)); + return FALSE; + } + this->threshold = mktime(&tm); + if (this->threshold == -1) + { + DBG1(DBG_CFG, "converting threshold for %s failed, disabled", + get_name(this)); + return FALSE; + } + if (time(NULL) >= this->threshold) + { + DBG1(DBG_CFG, "system time looks good, disabling %s", get_name(this)); + return FALSE; + } + + DBG1(DBG_CFG, "enabling %s, threshold: %s", get_name(this), asctime(&tm)); + this->validator = systime_fix_validator_create(this->threshold); + lib->credmgr->add_validator(lib->credmgr, &this->validator->validator); + + return TRUE; +} + +/** + * Plugin constructor + */ +plugin_t *systime_fix_plugin_create() +{ + private_systime_fix_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .reload = (void*)return_false, + .destroy = _destroy, + }, + }, + .interval = lib->settings->get_int(lib->settings, + "%s.plugins.%s.interval", 0, charon->name, get_name(this)), + .reauth = lib->settings->get_bool(lib->settings, + "%s.plugins.%s.reauth", FALSE, charon->name, get_name(this)), + ); + + if (load_validator(this)) + { + if (this->interval != 0) + { + DBG1(DBG_CFG, "starting systime check, interval: %ds", + this->interval); + lib->scheduler->schedule_job(lib->scheduler, (job_t*) + callback_job_create((callback_job_cb_t)check_systime, this, + NULL, NULL), this->interval); + } + } + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/systime_fix/systime_fix_plugin.h b/src/libcharon/plugins/systime_fix/systime_fix_plugin.h new file mode 100644 index 000000000..402659539 --- /dev/null +++ b/src/libcharon/plugins/systime_fix/systime_fix_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * 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 systime_fix systime_fix + * @ingroup cplugins + * + * @defgroup systime_fix_plugin systime_fix_plugin + * @{ @ingroup systime_fix + */ + +#ifndef SYSTIME_FIX_PLUGIN_H_ +#define SYSTIME_FIX_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct systime_fix_plugin_t systime_fix_plugin_t; + +/** + * Plugin handling cert lifetimes gracefully if system time is out of sync. + */ +struct systime_fix_plugin_t { + + /** + * Implements plugin interface. + */ + plugin_t plugin; +}; + +#endif /** SYSTIME_FIX_PLUGIN_H_ @}*/ diff --git a/src/libcharon/plugins/systime_fix/systime_fix_validator.c b/src/libcharon/plugins/systime_fix/systime_fix_validator.c new file mode 100644 index 000000000..340e86cbc --- /dev/null +++ b/src/libcharon/plugins/systime_fix/systime_fix_validator.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * 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 "systime_fix_validator.h" + +#include <errno.h> +#include <time.h> + +#include <daemon.h> + +typedef struct private_systime_fix_validator_t private_systime_fix_validator_t; + +/** + * Private data of an systime_fix_validator_t object. + */ +struct private_systime_fix_validator_t { + + /** + * Public systime_fix_validator_t interface. + */ + systime_fix_validator_t public; + + /** + * Timestamp where we start to consider system time valid + */ + time_t threshold; +}; + +METHOD(cert_validator_t, check_lifetime, status_t, + private_systime_fix_validator_t *this, certificate_t *cert, + int pathlen, bool anchor, auth_cfg_t *auth) +{ + if (time(NULL) < this->threshold) + { + /* our system time seems to be invalid, accept certificate */ + if (pathlen) + { /* report only once per validated chain */ + DBG1(DBG_CFG, "system time out of sync, skipping certificate " + "lifetime check"); + } + return SUCCESS; + } + /* validate this certificate normally */ + return NEED_MORE; +} + +METHOD(systime_fix_validator_t, destroy, void, + private_systime_fix_validator_t *this) +{ + free(this); +} + +/** + * See header + */ +systime_fix_validator_t *systime_fix_validator_create(time_t threshold) +{ + private_systime_fix_validator_t *this; + + INIT(this, + .public = { + .validator = { + .check_lifetime = _check_lifetime, + }, + .destroy = _destroy, + }, + .threshold = threshold, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/systime_fix/systime_fix_validator.h b/src/libcharon/plugins/systime_fix/systime_fix_validator.h new file mode 100644 index 000000000..3e651fd91 --- /dev/null +++ b/src/libcharon/plugins/systime_fix/systime_fix_validator.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * 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 systime_fix_validator systime_fix_validator + * @{ @ingroup systime_fix + */ + +#ifndef SYSTIME_FIX_VALIDATOR_H_ +#define SYSTIME_FIX_VALIDATOR_H_ + +#include <credentials/cert_validator.h> + +typedef struct systime_fix_validator_t systime_fix_validator_t; + +/** + * Validator that accepts cert lifetimes if system time is out of sync. + */ +struct systime_fix_validator_t { + + /** + * Implements cert_validator_t interface. + */ + cert_validator_t validator; + + /** + * Destroy a systime_fix_validator_t. + */ + void (*destroy)(systime_fix_validator_t *this); +}; + +/** + * Create a systime_fix_validator instance. + */ +systime_fix_validator_t *systime_fix_validator_create(); + +#endif /** SYSTIME_FIX_VALIDATOR_H_ @}*/ diff --git a/src/libcharon/plugins/tnc_imc/Makefile.am b/src/libcharon/plugins/tnc_imc/Makefile.am index 5e2c30df9..eba280690 100644 --- a/src/libcharon/plugins/tnc_imc/Makefile.am +++ b/src/libcharon/plugins/tnc_imc/Makefile.am @@ -4,7 +4,8 @@ INCLUDES = \ -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libtncif \ - -I$(top_srcdir)/src/libtnccs + -I$(top_srcdir)/src/libtnccs \ + -I$(top_srcdir)/src/libtls AM_CFLAGS = -rdynamic diff --git a/src/libcharon/plugins/tnc_imv/Makefile.am b/src/libcharon/plugins/tnc_imv/Makefile.am index eca3b377b..90b3507ce 100644 --- a/src/libcharon/plugins/tnc_imv/Makefile.am +++ b/src/libcharon/plugins/tnc_imv/Makefile.am @@ -4,7 +4,8 @@ INCLUDES = \ -I$(top_srcdir)/src/libhydra \ -I$(top_srcdir)/src/libcharon \ -I$(top_srcdir)/src/libtncif \ - -I$(top_srcdir)/src/libtnccs + -I$(top_srcdir)/src/libtnccs \ + -I$(top_srcdir)/src/libtls AM_CFLAGS = -rdynamic diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c index 39939d34e..422c28bc9 100644 --- a/src/libcharon/plugins/tnc_pdp/tnc_pdp.c +++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp.c @@ -378,7 +378,10 @@ static void process_eap(private_tnc_pdp_t *this, radius_message_t *request, } this->connections->add(this->connections, nas_id, user_name, peer, method); - method->initiate(method, &out); + if (method->initiate(method, &out) == NEED_MORE) + { + send_response(this, request, code, out, group, msk, source); + } } else { @@ -428,16 +431,16 @@ static void process_eap(private_tnc_pdp_t *this, radius_message_t *request, in->get_identifier(in)); } charon->bus->set_sa(charon->bus, NULL); + send_response(this, request, code, out, group, msk, source); + this->connections->unlock(this->connections); } - send_response(this, request, code, out, group, msk, source); - out->destroy(out); - if (code == RMC_ACCESS_ACCEPT || code == RMC_ACCESS_REJECT) { this->connections->remove(this->connections, nas_id, user_name); } + out->destroy(out); end: free(message.ptr); in->destroy(in); @@ -648,4 +651,3 @@ tnc_pdp_t *tnc_pdp_create(u_int16_t port) return &this->public; } - diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c index 0a960635b..f789c31d2 100644 --- a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c +++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.c @@ -17,6 +17,15 @@ #include <collections/linked_list.h> #include <utils/debug.h> +#include <threading/rwlock.h> +#include <processing/jobs/callback_job.h> + +#include <daemon.h> + +/** + * Default PDP connection timeout, in s + */ +#define DEFAULT_TIMEOUT 30 typedef struct private_tnc_pdp_connections_t private_tnc_pdp_connections_t; typedef struct entry_t entry_t; @@ -32,9 +41,19 @@ struct private_tnc_pdp_connections_t { tnc_pdp_connections_t public; /** - * List of TNC PEP RADIUS Connections + * TNC PEP RADIUS Connections */ linked_list_t *list; + + /** + * Lock to access PEP connection list + */ + rwlock_t *lock; + + /** + * Connection timeout before we kill non-completed connections, in s + */ + int timeout; }; /** @@ -61,6 +80,11 @@ struct entry_t { * IKE SA used for bus communication */ ike_sa_t *ike_sa; + + /** + * Timestamp this entry has been created + */ + time_t created; }; /** @@ -105,6 +129,35 @@ static void dbg_nas_user(chunk_t nas_id, chunk_t user_name, bool not, char *op) } } +/** + * Check if any connection has timed out + */ +static job_requeue_t check_timeouts(private_tnc_pdp_connections_t *this) +{ + enumerator_t *enumerator; + entry_t *entry; + time_t now; + + now = time_monotonic(NULL); + + this->lock->write_lock(this->lock); + enumerator = this->list->create_enumerator(this->list); + while (enumerator->enumerate(enumerator, &entry)) + { + if (entry->created + this->timeout <= now) + { + DBG1(DBG_CFG, "RADIUS connection timed out after %d seconds", + this->timeout); + this->list->remove_at(this->list, enumerator); + free_entry(entry); + } + } + enumerator->destroy(enumerator); + this->lock->unlock(this->lock); + + return JOB_REQUEUE_NONE; +} + METHOD(tnc_pdp_connections_t, add, void, private_tnc_pdp_connections_t *this, chunk_t nas_id, chunk_t user_name, identification_t *peer, eap_method_t *method) @@ -120,6 +173,7 @@ METHOD(tnc_pdp_connections_t, add, void, ike_sa_id->destroy(ike_sa_id); ike_sa->set_other_id(ike_sa, peer); + this->lock->read_lock(this->lock); enumerator = this->list->create_enumerator(this->list); while (enumerator->enumerate(enumerator, &entry)) { @@ -131,20 +185,33 @@ METHOD(tnc_pdp_connections_t, add, void, DBG1(DBG_CFG, "removed stale RADIUS connection"); entry->method = method; entry->ike_sa = ike_sa; + entry->created = time_monotonic(NULL); break; } } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); if (!found) { - entry = malloc_thing(entry_t); - entry->nas_id = chunk_clone(nas_id); - entry->user_name = chunk_clone(user_name); - entry->method = method; - entry->ike_sa = ike_sa; + INIT(entry, + .nas_id = chunk_clone(nas_id), + .user_name = chunk_clone(user_name), + .method = method, + .ike_sa = ike_sa, + .created = time_monotonic(NULL), + ); + this->lock->write_lock(this->lock); this->list->insert_last(this->list, entry); + this->lock->unlock(this->lock); } + + /* schedule timeout checking */ + lib->scheduler->schedule_job_ms(lib->scheduler, + (job_t*)callback_job_create((callback_job_cb_t)check_timeouts, + this, NULL, (callback_job_cancel_t)return_false), + this->timeout * 1000); + dbg_nas_user(nas_id, user_name, FALSE, "created"); } @@ -154,6 +221,7 @@ METHOD(tnc_pdp_connections_t, remove_, void, enumerator_t *enumerator; entry_t *entry; + this->lock->write_lock(this->lock); enumerator = this->list->create_enumerator(this->list); while (enumerator->enumerate(enumerator, &entry)) { @@ -166,6 +234,7 @@ METHOD(tnc_pdp_connections_t, remove_, void, } } enumerator->destroy(enumerator); + this->lock->unlock(this->lock); } METHOD(tnc_pdp_connections_t, get_state, eap_method_t*, @@ -176,6 +245,7 @@ METHOD(tnc_pdp_connections_t, get_state, eap_method_t*, entry_t *entry; eap_method_t *found = NULL; + this->lock->read_lock(this->lock); enumerator = this->list->create_enumerator(this->list); while (enumerator->enumerate(enumerator, &entry)) { @@ -187,14 +257,25 @@ METHOD(tnc_pdp_connections_t, get_state, eap_method_t*, } } enumerator->destroy(enumerator); + if (!found) + { + this->lock->unlock(this->lock); + } dbg_nas_user(nas_id, user_name, !found, "found"); return found; } +METHOD(tnc_pdp_connections_t, unlock, void, + private_tnc_pdp_connections_t *this) +{ + this->lock->unlock(this->lock); +} + METHOD(tnc_pdp_connections_t, destroy, void, private_tnc_pdp_connections_t *this) { + this->lock->destroy(this->lock); this->list->destroy_function(this->list, (void*)free_entry); free(this); } @@ -211,11 +292,14 @@ tnc_pdp_connections_t *tnc_pdp_connections_create(void) .add = _add, .remove = _remove_, .get_state = _get_state, + .unlock = _unlock, .destroy = _destroy, }, .list = linked_list_create(), + .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), + .timeout = lib->settings->get_int(lib->settings, + "%s.plugins.tnc-pdp.timeout", DEFAULT_TIMEOUT, charon->name), ); return &this->public; } - diff --git a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h index 16492020e..442f29ce9 100644 --- a/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h +++ b/src/libcharon/plugins/tnc_pdp/tnc_pdp_connections.h @@ -53,7 +53,10 @@ struct tnc_pdp_connections_t { chunk_t user_name); /** - * Get the EAP method and IKE_SA of a registered TNC PEP RADIUS Connection + * Get the EAP method and IKE_SA of a registered TNC PEP RADIUS Connection. + * + * If this call succeeds, the connection manager is locked. Call unlock + * after using the return objects. * * @param nas_id NAS identifier of Policy Enforcement Point * @param user_name User name of TNC Client @@ -64,6 +67,11 @@ struct tnc_pdp_connections_t { chunk_t user_name, ike_sa_t **ike_sa); /** + * Unlock connections after successfully calling get_state(). + */ + void (*unlock)(tnc_pdp_connections_t *this); + + /** * Destroys a tnc_pdp_connections_t object. */ void (*destroy)(tnc_pdp_connections_t *this); diff --git a/src/libcharon/plugins/tnc_tnccs/Makefile.am b/src/libcharon/plugins/tnc_tnccs/Makefile.am index c7fc02f7c..9ee9e86ad 100644 --- a/src/libcharon/plugins/tnc_tnccs/Makefile.am +++ b/src/libcharon/plugins/tnc_tnccs/Makefile.am @@ -1,6 +1,7 @@ INCLUDES = \ -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtls \ -I$(top_srcdir)/src/libtncif \ -I$(top_srcdir)/src/libtnccs diff --git a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c index 0b623d6ff..6ddda594d 100644 --- a/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c +++ b/src/libcharon/plugins/tnc_tnccs/tnc_tnccs_manager.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -20,7 +20,13 @@ #include <tnc/imc/imc_manager.h> #include <tnc/imv/imv_manager.h> +#include <tncif_identity.h> + +#include <tls.h> + #include <utils/debug.h> +#include <pen/pen.h> +#include <bio/bio_writer.h> #include <collections/linked_list.h> #include <threading/rwlock.h> @@ -158,7 +164,9 @@ METHOD(tnccs_manager_t, remove_method, void, } METHOD(tnccs_manager_t, create_instance, tnccs_t*, - private_tnc_tnccs_manager_t *this, tnccs_type_t type, bool is_server) + private_tnc_tnccs_manager_t *this, tnccs_type_t type, bool is_server, + identification_t *server, identification_t *peer, + tnc_ift_type_t transport) { enumerator_t *enumerator; tnccs_entry_t *entry; @@ -170,7 +178,7 @@ METHOD(tnccs_manager_t, create_instance, tnccs_t*, { if (type == entry->type) { - protocol = entry->constructor(is_server); + protocol = entry->constructor(is_server, server, peer, transport); if (protocol) { break; @@ -442,6 +450,44 @@ static TNC_Result str_attribute(TNC_UInt32 buffer_len, } } +/** + * Write the value of a TNC identity list into the buffer + */ +static TNC_Result identity_attribute(TNC_UInt32 buffer_len, + TNC_BufferReference buffer, + TNC_UInt32 *value_len, + linked_list_t *list) +{ + bio_writer_t *writer; + enumerator_t *enumerator; + u_int32_t count; + chunk_t value; + tncif_identity_t *tnc_id; + TNC_Result result = TNC_RESULT_INVALID_PARAMETER; + + count = list->get_count(list); + writer = bio_writer_create(4 + TNCIF_IDENTITY_MIN_SIZE * count); + writer->write_uint32(writer, count); + + enumerator = list->create_enumerator(list); + while (enumerator->enumerate(enumerator, &tnc_id)) + { + tnc_id->build(tnc_id, writer); + } + enumerator->destroy(enumerator); + + value = writer->get_buf(writer); + *value_len = value.len; + if (buffer && buffer_len >= value.len) + { + memcpy(buffer, value.ptr, value.len); + result = TNC_RESULT_SUCCESS; + } + writer->destroy(writer); + + return result; +} + METHOD(tnccs_manager_t, get_attribute, TNC_Result, private_tnc_tnccs_manager_t *this, bool is_imc, TNC_UInt32 imcv_id, @@ -487,6 +533,7 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result, /* these attributes are supported */ case TNC_ATTRIBUTEID_PRIMARY_IMV_ID: + case TNC_ATTRIBUTEID_AR_IDENTITIES: attribute_match = TRUE; break; @@ -616,15 +663,111 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result, version = "1.0"; break; default: - return TNC_RESULT_INVALID_PARAMETER; + return TNC_RESULT_INVALID_PARAMETER; } return str_attribute(buffer_len, buffer, value_len, version); } case TNC_ATTRIBUTEID_IFT_PROTOCOL: - return str_attribute(buffer_len, buffer, value_len, - "IF-T for Tunneled EAP"); + { + char *protocol; + + switch (entry->tnccs->get_transport(entry->tnccs)) + { + case TNC_IFT_EAP_1_0: + case TNC_IFT_EAP_1_1: + case TNC_IFT_EAP_2_0: + protocol = "IF-T for Tunneled EAP"; + break; + case TNC_IFT_TLS_1_0: + case TNC_IFT_TLS_2_0: + protocol = "IF-T for TLS"; + break; + default: + return TNC_RESULT_INVALID_PARAMETER; + } + return str_attribute(buffer_len, buffer, value_len, protocol); + } case TNC_ATTRIBUTEID_IFT_VERSION: - return str_attribute(buffer_len, buffer, value_len, "1.1"); + { + char *version; + + switch (entry->tnccs->get_transport(entry->tnccs)) + { + case TNC_IFT_EAP_1_0: + case TNC_IFT_TLS_1_0: + version = "1.0"; + break; + case TNC_IFT_EAP_1_1: + version = "1.1"; + break; + case TNC_IFT_EAP_2_0: + case TNC_IFT_TLS_2_0: + version = "2.0"; + break; + default: + return TNC_RESULT_INVALID_PARAMETER; + } + return str_attribute(buffer_len, buffer, value_len, version); + } + case TNC_ATTRIBUTEID_AR_IDENTITIES: + { + linked_list_t *list; + identification_t *peer; + tnccs_t *tnccs; + tncif_identity_t *tnc_id; + u_int32_t id_type, subject_type; + TNC_Result result; + + list = linked_list_create(); + tnccs = entry->tnccs; + peer = tnccs->tls.get_peer_id(&tnccs->tls); + if (peer) + { + switch (peer->get_type(peer)) + { + case ID_IPV4_ADDR: + id_type = TNC_ID_IPV4_ADDR; + subject_type = TNC_SUBJECT_MACHINE; + break; + case ID_IPV6_ADDR: + id_type = TNC_ID_IPV6_ADDR; + subject_type = TNC_SUBJECT_MACHINE; + break; + case ID_FQDN: + id_type = TNC_ID_USER_NAME; + subject_type = TNC_SUBJECT_USER; + break; + case ID_RFC822_ADDR: + id_type = TNC_ID_RFC822_ADDR; + subject_type = TNC_SUBJECT_USER; + break; + case ID_DER_ASN1_DN: + id_type = TNC_ID_DER_ASN1_DN; + subject_type = TNC_SUBJECT_USER; + break; + case ID_DER_ASN1_GN: + id_type = TNC_ID_DER_ASN1_GN; + subject_type = TNC_SUBJECT_UNKNOWN; + break; + default: + id_type = TNC_ID_UNKNOWN; + subject_type = TNC_SUBJECT_UNKNOWN; + } + if (id_type != TNC_ID_UNKNOWN) + { + tnc_id = tncif_identity_create( + pen_type_create(PEN_TCG, id_type), + peer->get_encoding(peer), + pen_type_create(PEN_TCG, subject_type), + pen_type_create(PEN_TCG, + tnccs->get_auth_type(tnccs))); + list->insert_last(list, tnc_id); + } + } + result = identity_attribute(buffer_len, buffer, value_len, list); + list->destroy_offset(list, offsetof(tncif_identity_t, destroy)); + return result; + } default: return TNC_RESULT_INVALID_PARAMETER; } diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.c b/src/libcharon/plugins/tnccs_11/tnccs_11.c index cfc29d6ab..53817c710 100644 --- a/src/libcharon/plugins/tnccs_11/tnccs_11.c +++ b/src/libcharon/plugins/tnccs_11/tnccs_11.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -43,9 +43,9 @@ typedef struct private_tnccs_11_t private_tnccs_11_t; struct private_tnccs_11_t { /** - * Public tls_t interface. + * Public tnccs_t interface. */ - tls_t public; + tnccs_t public; /** * TNCC if TRUE, TNCS if FALSE @@ -53,6 +53,26 @@ struct private_tnccs_11_t { bool is_server; /** + * Server identity + */ + identification_t *server; + + /** + * Client identity + */ + identification_t *peer; + + /** + * Underlying TNC IF-T transport protocol + */ + tnc_ift_type_t transport; + + /** + * Type of TNC client authentication + */ + u_int32_t auth_type; + + /** * Connection ID assigned to this TNCCS connection */ TNC_ConnectionID connection_id; @@ -495,6 +515,18 @@ METHOD(tls_t, is_server, bool, return this->is_server; } +METHOD(tls_t, get_server_id, identification_t*, + private_tnccs_11_t *this) +{ + return this->server; +} + +METHOD(tls_t, get_peer_id, identification_t*, + private_tnccs_11_t *this) +{ + return this->peer; +} + METHOD(tls_t, get_purpose, tls_purpose_t, private_tnccs_11_t *this) { @@ -528,29 +560,69 @@ METHOD(tls_t, destroy, void, { tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id, this->is_server); + this->server->destroy(this->server); + this->peer->destroy(this->peer); this->mutex->destroy(this->mutex); DESTROY_IF(this->batch); free(this); } +METHOD(tnccs_t, get_transport, tnc_ift_type_t, + private_tnccs_11_t *this) +{ + return this->transport; +} + +METHOD(tnccs_t, set_transport, void, + private_tnccs_11_t *this, tnc_ift_type_t transport) +{ + this->transport = transport; +} + +METHOD(tnccs_t, get_auth_type, u_int32_t, + private_tnccs_11_t *this) +{ + return this->auth_type; +} + +METHOD(tnccs_t, set_auth_type, void, + private_tnccs_11_t *this, u_int32_t auth_type) +{ + this->auth_type = auth_type; +} + /** * See header */ -tls_t *tnccs_11_create(bool is_server) +tnccs_t* tnccs_11_create(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport) { private_tnccs_11_t *this; INIT(this, .public = { - .process = _process, - .build = _build, - .is_server = _is_server, - .get_purpose = _get_purpose, - .is_complete = _is_complete, - .get_eap_msk = _get_eap_msk, - .destroy = _destroy, + .tls = { + .process = _process, + .build = _build, + .is_server = _is_server, + .get_server_id = _get_server_id, + .get_peer_id = _get_peer_id, + .get_purpose = _get_purpose, + .is_complete = _is_complete, + .get_eap_msk = _get_eap_msk, + .destroy = _destroy, + }, + .get_transport = _get_transport, + .set_transport = _set_transport, + .get_auth_type = _get_auth_type, + .set_auth_type = _set_auth_type, }, .is_server = is_server, + .server = server->clone(server), + .peer = peer->clone(peer), + .transport = transport, .mutex = mutex_create(MUTEX_TYPE_DEFAULT), .max_msg_len = lib->settings->get_int(lib->settings, "%s.plugins.tnccs-11.max_message_size", 45000, diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11.h b/src/libcharon/plugins/tnccs_11/tnccs_11.h index 7331fc8cd..531ebb611 100644 --- a/src/libcharon/plugins/tnccs_11/tnccs_11.h +++ b/src/libcharon/plugins/tnccs_11/tnccs_11.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -23,14 +23,20 @@ #include <library.h> -#include <tls.h> +#include <tnc/tnccs/tnccs.h> /** * Create an instance of the TNC IF-TNCCS 1.1 protocol handler. * - * @param is_server TRUE to act as TNC Server, FALSE for TNC Client - * @return TNC_IF_TNCCS 1.1 protocol stack + * @param is_server TRUE to act as TNC Server, FALSE for TNC Client + * @param server Server identity + * @param peer Client identity + * @param transport Underlying IF-T transport protocol + * @return TNC_IF_TNCCS 1.1 protocol stack */ -tls_t *tnccs_11_create(bool is_server); +tnccs_t* tnccs_11_create(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport); #endif /** TNCCS_11_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c b/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c index cd95afb1e..f534af008 100644 --- a/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c +++ b/src/libcharon/plugins/tnccs_11/tnccs_11_plugin.c @@ -30,8 +30,6 @@ METHOD(plugin_t, get_features, int, static plugin_feature_t f[] = { PLUGIN_CALLBACK(tnccs_method_register, tnccs_11_create), PLUGIN_PROVIDE(CUSTOM, "tnccs-1.1"), - PLUGIN_DEPENDS(EAP_SERVER, EAP_TNC), - PLUGIN_DEPENDS(EAP_PEER, EAP_TNC), PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"), }; *features = f; @@ -61,4 +59,3 @@ plugin_t *tnccs_11_plugin_create() return &this->plugin; } - diff --git a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c index 3a2c70f5a..d87e0ccea 100644 --- a/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c +++ b/src/libcharon/plugins/tnccs_20/batch/pb_tnc_batch.c @@ -201,7 +201,7 @@ METHOD(pb_tnc_batch_t, build, void, } enumerator->destroy(enumerator); - this->encoding = chunk_clone(writer->get_buf(writer)); + this->encoding = writer->extract_buf(writer); writer->destroy(writer); } @@ -386,6 +386,13 @@ static status_t process_tnc_msg(private_pb_tnc_batch_t *this) } else { + if (msg_type == PB_MSG_EXPERIMENTAL && noskip_flag) + { + DBG1(DBG_TNC, "reject PB-Experimental message with NOSKIP flag set"); + msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF, + PB_ERROR_UNSUPPORTED_MANDATORY_MSG, this->offset); + goto fatal; + } if (pb_tnc_msg_infos[msg_type].has_noskip_flag != TRUE_OR_FALSE && pb_tnc_msg_infos[msg_type].has_noskip_flag != noskip_flag) { diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c index 2d2c1316b..aa5e9c723 100644 --- a/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c +++ b/src/libcharon/plugins/tnccs_20/messages/pb_pa_msg.c @@ -166,6 +166,7 @@ METHOD(pb_tnc_msg_t, process, status_t, { DBG1(DBG_TNC, "PA Subtype 0x%08x is reserved", PA_RESERVED_SUBTYPE); *offset = 4; + return FAILED; } return SUCCESS; diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c index 63d94b94d..2ef8dd6cd 100644 --- a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c +++ b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.c @@ -66,24 +66,24 @@ struct private_pb_remediation_parameters_msg_t { pb_tnc_msg_type_t type; /** - * Remediation Parameters Vendor ID + * Remediation Parameters Type */ - u_int32_t vendor_id; + pen_type_t parameters_type; /** - * Remediation Parameters Type + * Remediation Parameters */ - u_int32_t parameters_type; + chunk_t parameters; /** - * Remediation Parameters string + * Remediation String */ - chunk_t remediation_string; + chunk_t string; /** - * Language code + * Remediation Language Code */ - chunk_t language_code; + chunk_t lang_code; /** * Encoded message @@ -113,10 +113,9 @@ METHOD(pb_tnc_msg_t, build, void, return; } writer = bio_writer_create(64); - writer->write_uint32(writer, this->vendor_id); - writer->write_uint32(writer, this->parameters_type); - writer->write_data32(writer, this->remediation_string); - writer->write_data8 (writer, this->language_code); + writer->write_uint32(writer, this->parameters_type.vendor_id); + writer->write_uint32(writer, this->parameters_type.type); + writer->write_data32(writer, this->parameters); this->encoding = writer->get_buf(writer); this->encoding = chunk_clone(this->encoding); @@ -127,83 +126,103 @@ METHOD(pb_tnc_msg_t, process, status_t, private_pb_remediation_parameters_msg_t *this, u_int32_t *offset) { bio_reader_t *reader; + u_int8_t reserved; + status_t status = SUCCESS; + u_char *pos; + + *offset = 0; /* process message */ reader = bio_reader_create(this->encoding); - reader->read_uint32(reader, &this->vendor_id); - reader->read_uint32(reader, &this->parameters_type); + reader->read_uint8 (reader, &reserved); + reader->read_uint24(reader, &this->parameters_type.vendor_id); + reader->read_uint32(reader, &this->parameters_type.type); + reader->read_data (reader, reader->remaining(reader), &this->parameters); - if (!reader->read_data32(reader, &this->remediation_string)) + this->parameters = chunk_clone(this->parameters); + reader->destroy(reader); + + if (this->parameters_type.vendor_id == PEN_IETF && + this->parameters_type.type == PB_REMEDIATION_STRING) { - DBG1(DBG_TNC, "could not parse remediation string"); - reader->destroy(reader); + reader = bio_reader_create(this->parameters); + status = FAILED; *offset = 8; - return FAILED; - }; - this->remediation_string = chunk_clone(this->remediation_string); - if (this->remediation_string.len && - this->remediation_string.ptr[this->remediation_string.len-1] == '\0') - { - DBG1(DBG_TNC, "remediation string must not be null terminated"); + if (!reader->read_data32(reader, &this->string)) + { + DBG1(DBG_TNC, "insufficient data for remediation string"); + goto end; + }; + *offset += 4; + + pos = memchr(this->string.ptr, '\0', this->string.len); + if (pos) + { + DBG1(DBG_TNC, "nul termination in remediation string"); + *offset += (pos - this->string.ptr); + goto end; + } + *offset += this->string.len; + + if (!reader->read_data8(reader, &this->lang_code)) + { + DBG1(DBG_TNC, "insufficient data for remediation string lang code"); + goto end; + }; + *offset += 1; + + pos = memchr(this->lang_code.ptr, '\0', this->lang_code.len); + + if (pos) + { + DBG1(DBG_TNC, "nul termination in remediation string lang code"); + *offset += (pos - this->lang_code.ptr); + goto end; + } + status = SUCCESS; + +end: reader->destroy(reader); - *offset = 11 + this->remediation_string.len; - return FAILED; } - - if (!reader->read_data8(reader, &this->language_code)) - { - DBG1(DBG_TNC, "could not parse language code"); - reader->destroy(reader); - *offset = 12 + this->remediation_string.len; - return FAILED; - }; - this->language_code = chunk_clone(this->language_code); - reader->destroy(reader); - - if (this->language_code.len && - this->language_code.ptr[this->language_code.len-1] == '\0') - { - DBG1(DBG_TNC, "language code must not be null terminated"); - *offset = 12 + this->remediation_string.len + this->language_code.len; - return FAILED; - } - - return SUCCESS; + return status; } METHOD(pb_tnc_msg_t, destroy, void, private_pb_remediation_parameters_msg_t *this) { free(this->encoding.ptr); - free(this->remediation_string.ptr); - free(this->language_code.ptr); + free(this->parameters.ptr); free(this); } -METHOD(pb_remediation_parameters_msg_t, get_vendor_id, u_int32_t, - private_pb_remediation_parameters_msg_t *this, u_int32_t *type) +METHOD(pb_remediation_parameters_msg_t, get_parameters_type, pen_type_t, + private_pb_remediation_parameters_msg_t *this) { - *type = this->parameters_type; - return this->vendor_id; + return this->parameters_type; } -METHOD(pb_remediation_parameters_msg_t, get_remediation_string, chunk_t, +METHOD(pb_remediation_parameters_msg_t, get_parameters, chunk_t, private_pb_remediation_parameters_msg_t *this) { - return this->remediation_string; + return this->parameters; } -METHOD(pb_remediation_parameters_msg_t, get_language_code, chunk_t, - private_pb_remediation_parameters_msg_t *this) +METHOD(pb_remediation_parameters_msg_t, get_string, chunk_t, + private_pb_remediation_parameters_msg_t *this, chunk_t *lang_code) { - return this->language_code; + if (lang_code) + { + *lang_code = this->lang_code; + } + return this->string; } /** * See header */ -pb_tnc_msg_t *pb_remediation_parameters_msg_create_from_data(chunk_t data) +pb_tnc_msg_t* pb_remediation_parameters_msg_create(pen_type_t parameters_type, + chunk_t parameters) { private_pb_remediation_parameters_msg_t *this; @@ -216,24 +235,56 @@ pb_tnc_msg_t *pb_remediation_parameters_msg_create_from_data(chunk_t data) .process = _process, .destroy = _destroy, }, - .get_vendor_id = _get_vendor_id, - .get_remediation_string = _get_remediation_string, - .get_language_code = _get_language_code, + .get_parameters_type = _get_parameters_type, + .get_parameters = _get_parameters, + .get_uri = _get_parameters, + .get_string = _get_string, }, - .type = PB_MSG_REASON_STRING, - .encoding = chunk_clone(data), + .type = PB_MSG_REMEDIATION_PARAMETERS, + .parameters_type = parameters_type, + .parameters = chunk_clone(parameters), ); return &this->public.pb_interface; } /** + * Described in header. + */ +pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_uri(chunk_t uri) +{ + pen_type_t type = { PEN_IETF, PB_REMEDIATION_URI }; + + return pb_remediation_parameters_msg_create(type, uri); +} + +/** + * Described in header. + */ +pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_string(chunk_t string, + chunk_t lang_code) +{ + pb_tnc_msg_t *msg; + bio_writer_t *writer; + pen_type_t type = { PEN_IETF, PB_REMEDIATION_STRING }; + + /* limit language code to 255 octets */ + lang_code.len = min(255, lang_code.len); + + writer = bio_writer_create(4 + string.len + 1 + lang_code.len); + writer->write_data32(writer, string); + writer->write_data8 (writer, lang_code); + + msg = pb_remediation_parameters_msg_create(type, writer->get_buf(writer)); + writer->destroy(writer); + + return msg; +} + +/** * See header */ -pb_tnc_msg_t* pb_remediation_parameters_msg_create(u_int32_t vendor_id, - u_int32_t type, - chunk_t remediation_string, - chunk_t language_code) +pb_tnc_msg_t *pb_remediation_parameters_msg_create_from_data(chunk_t data) { private_pb_remediation_parameters_msg_t *this; @@ -246,16 +297,15 @@ pb_tnc_msg_t* pb_remediation_parameters_msg_create(u_int32_t vendor_id, .process = _process, .destroy = _destroy, }, - .get_vendor_id = _get_vendor_id, - .get_remediation_string = _get_remediation_string, - .get_language_code = _get_language_code, + .get_parameters_type = _get_parameters_type, + .get_parameters = _get_parameters, + .get_uri = _get_parameters, + .get_string = _get_string, }, - .type = PB_MSG_REASON_STRING, - .vendor_id = vendor_id, - .parameters_type = type, - .remediation_string = chunk_clone(remediation_string), - .language_code = chunk_clone(language_code), + .type = PB_MSG_REMEDIATION_PARAMETERS, + .encoding = chunk_clone(data), ); return &this->public.pb_interface; } + diff --git a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h index 258d495ec..f3a1c1009 100644 --- a/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h +++ b/src/libcharon/plugins/tnccs_20/messages/pb_remediation_parameters_msg.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Andreas Steffen + * Copyright (C) 2011-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ typedef struct pb_remediation_parameters_msg_t pb_remediation_parameters_msg_t; #include "pb_tnc_msg.h" +#include <pen/pen.h> + /** * PB-TNC Remediation Parameter Types as defined in section 4.8.1 of RFC 5793 */ @@ -50,41 +52,61 @@ struct pb_remediation_parameters_msg_t { pb_tnc_msg_t pb_interface; /** - * Get Remediation Parameters Vendor ID and Type + * Get the Remediation Parameters Type (Vendor ID and Type) * - * @param type Remediation Parameters Type - * @return Remediation Parameters Vendor ID + * @return Remediation Parameters Type */ - u_int32_t (*get_vendor_id)(pb_remediation_parameters_msg_t *this, - u_int32_t *type); + pen_type_t (*get_parameters_type)(pb_remediation_parameters_msg_t *this); /** - * Get Remediation String + * Get the Remediation Parameters * - * @return Remediation String + * @return Remediation Parameters */ - chunk_t (*get_remediation_string)(pb_remediation_parameters_msg_t *this); + chunk_t (*get_parameters)(pb_remediation_parameters_msg_t *this); /** - * Get Reason String Language Code + * Get the Remediation URI * - * @return Language Code + * @return Remediation URI */ - chunk_t (*get_language_code)(pb_remediation_parameters_msg_t *this); + chunk_t (*get_uri)(pb_remediation_parameters_msg_t *this); + + /** + * Get the Remediation String + * + * @param lang_code Optional Language Code + * @return Remediation String + */ + chunk_t (*get_string)(pb_remediation_parameters_msg_t *this, + chunk_t *lang_code); + }; /** - * Create a PB-Remediation-Parameters message from parameters + * Create a general PB-Remediation-Parameters message + * + * @param parameters_type Remediation Parameters Type + * @param parameters Remediation Parameters + */ +pb_tnc_msg_t* pb_remediation_parameters_msg_create(pen_type_t parameters_type, + chunk_t parameters); + +/** + * Create a PB-Remediation-Parameters message of IETF Type Remediation URI + * + * @param uri Remediation URI + */ +pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_uri(chunk_t uri); + +/** + * Create a PB-Remediation-Parameters message of IETF Type Remediation String * - * @param vendor_id Remediation Parameters Vendor ID - * @param type Remediation Parameters Type - * @param remediation_string Remediation String - * @param language_code Language Code + * @param string Remediation String + * @param lang_code Remediation String Language Code */ -pb_tnc_msg_t* pb_remediation_parameters_msg_create(u_int32_t vendor_id, - u_int32_t type, - chunk_t remediation_string, - chunk_t language_code); +pb_tnc_msg_t* pb_remediation_parameters_msg_create_from_string(chunk_t string, + chunk_t lang_code); /** * Create an unprocessed PB-Remediation-Parameters message from raw data diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.c b/src/libcharon/plugins/tnccs_20/tnccs_20.c index 6239b152d..29a161e69 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2010 Sansar Choinyanbuu - * Copyright (C) 2010-2012 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -48,9 +48,9 @@ typedef struct private_tnccs_20_t private_tnccs_20_t; struct private_tnccs_20_t { /** - * Public tls_t interface. + * Public tnccs_t interface. */ - tls_t public; + tnccs_t public; /** * TNCC if TRUE, TNCS if FALSE @@ -58,6 +58,26 @@ struct private_tnccs_20_t { bool is_server; /** + * Server identity + */ + identification_t *server; + + /** + * Client identity + */ + identification_t *peer; + + /** + * Underlying TNC IF-T transport protocol + */ + tnc_ift_type_t transport; + + /** + * Type of TNC client authentication + */ + u_int32_t auth_type; + + /** * PB-TNC State Machine */ pb_tnc_state_machine_t *state_machine; @@ -291,7 +311,36 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg) } case PB_MSG_REMEDIATION_PARAMETERS: { - /* TODO : Remediation parameters message processing */ + pb_remediation_parameters_msg_t *rem_msg; + pen_type_t parameters_type; + chunk_t parameters, string, lang_code; + + rem_msg = (pb_remediation_parameters_msg_t*)msg; + parameters_type = rem_msg->get_parameters_type(rem_msg); + parameters = rem_msg->get_parameters(rem_msg); + + if (parameters_type.vendor_id == PEN_IETF) + { + switch (parameters_type.type) + { + case PB_REMEDIATION_URI: + DBG1(DBG_TNC, "remediation uri: %.*s", + parameters.len, parameters.ptr); + break; + case PB_REMEDIATION_STRING: + string = rem_msg->get_string(rem_msg, &lang_code); + DBG1(DBG_TNC, "remediation string: [%.*s]\n%.*s", + lang_code.len, lang_code.ptr, + string.len, string.ptr); + break; + default: + DBG1(DBG_TNC, "remediation parameters: %B", ¶meters); + } + } + else + { + DBG1(DBG_TNC, "remediation parameters: %B", ¶meters); + } break; } case PB_MSG_ERROR: @@ -356,9 +405,12 @@ static void handle_message(private_tnccs_20_t *this, pb_tnc_msg_t *msg) lang_msg = (pb_language_preference_msg_t*)msg; lang = lang_msg->get_language_preference(lang_msg); - DBG2(DBG_TNC, "setting language preference to '%.*s'", - (int)lang.len, lang.ptr); - this->recs->set_preferred_language(this->recs, lang); + if (this->recs) + { + DBG2(DBG_TNC, "setting language preference to '%.*s'", + (int)lang.len, lang.ptr); + this->recs->set_preferred_language(this->recs, lang); + } break; } case PB_MSG_REASON_STRING: @@ -759,6 +811,18 @@ METHOD(tls_t, is_server, bool, return this->is_server; } +METHOD(tls_t, get_server_id, identification_t*, + private_tnccs_20_t *this) +{ + return this->server; +} + +METHOD(tls_t, get_peer_id, identification_t*, + private_tnccs_20_t *this) +{ + return this->peer; +} + METHOD(tls_t, get_purpose, tls_purpose_t, private_tnccs_20_t *this) { @@ -792,6 +856,8 @@ METHOD(tls_t, destroy, void, { tnc->tnccs->remove_connection(tnc->tnccs, this->connection_id, this->is_server); + this->server->destroy(this->server); + this->peer->destroy(this->peer); this->state_machine->destroy(this->state_machine); this->mutex->destroy(this->mutex); this->messages->destroy_offset(this->messages, @@ -799,24 +865,62 @@ METHOD(tls_t, destroy, void, free(this); } +METHOD(tnccs_t, get_transport, tnc_ift_type_t, + private_tnccs_20_t *this) +{ + return this->transport; +} + +METHOD(tnccs_t, set_transport, void, + private_tnccs_20_t *this, tnc_ift_type_t transport) +{ + this->transport = transport; +} + +METHOD(tnccs_t, get_auth_type, u_int32_t, + private_tnccs_20_t *this) +{ + return this->auth_type; +} + +METHOD(tnccs_t, set_auth_type, void, + private_tnccs_20_t *this, u_int32_t auth_type) +{ + this->auth_type = auth_type; +} + /** * See header */ -tls_t *tnccs_20_create(bool is_server) +tnccs_t* tnccs_20_create(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport) { private_tnccs_20_t *this; INIT(this, .public = { - .process = _process, - .build = _build, - .is_server = _is_server, - .get_purpose = _get_purpose, - .is_complete = _is_complete, - .get_eap_msk = _get_eap_msk, - .destroy = _destroy, + .tls = { + .process = _process, + .build = _build, + .is_server = _is_server, + .get_server_id = _get_server_id, + .get_peer_id = _get_peer_id, + .get_purpose = _get_purpose, + .is_complete = _is_complete, + .get_eap_msk = _get_eap_msk, + .destroy = _destroy, + }, + .get_transport = _get_transport, + .set_transport = _set_transport, + .get_auth_type = _get_auth_type, + .set_auth_type = _set_auth_type, }, .is_server = is_server, + .server = server->clone(server), + .peer = peer->clone(peer), + .transport = transport, .state_machine = pb_tnc_state_machine_create(is_server), .mutex = mutex_create(MUTEX_TYPE_DEFAULT), .messages = linked_list_create(), diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20.h b/src/libcharon/plugins/tnccs_20/tnccs_20.h index 400d1dc12..314935069 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20.h +++ b/src/libcharon/plugins/tnccs_20/tnccs_20.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -23,14 +23,20 @@ #include <library.h> -#include <tls.h> +#include <tnc/tnccs/tnccs.h> /** * Create an instance of the TNC IF-TNCCS 2.0 protocol handler. * - * @param is_server TRUE to act as TNC Server, FALSE for TNC Client - * @return TNC_IF_TNCCS 2.0 protocol stack + * @param is_server TRUE to act as TNC Server, FALSE for TNC Client + * @param server Server identity + * @param peer Client identity + * @param transport Underlying IF-T transport protocol + * @return TNC_IF_TNCCS 2.0 protocol stack */ -tls_t *tnccs_20_create(bool is_server); +tnccs_t* tnccs_20_create(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport); #endif /** TNCCS_20_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c b/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c index 4f419ecf0..f74306c8c 100644 --- a/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c +++ b/src/libcharon/plugins/tnccs_20/tnccs_20_plugin.c @@ -30,8 +30,6 @@ METHOD(plugin_t, get_features, int, static plugin_feature_t f[] = { PLUGIN_CALLBACK(tnccs_method_register, tnccs_20_create), PLUGIN_PROVIDE(CUSTOM, "tnccs-2.0"), - PLUGIN_DEPENDS(EAP_SERVER, EAP_TNC), - PLUGIN_DEPENDS(EAP_PEER, EAP_TNC), PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"), }; *features = f; @@ -61,4 +59,3 @@ plugin_t *tnccs_20_plugin_create() return &this->plugin; } - diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c index 03795a947..d4fc6a6f7 100644 --- a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c +++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -27,14 +27,35 @@ typedef struct private_tnccs_dynamic_t private_tnccs_dynamic_t; struct private_tnccs_dynamic_t { /** - * Public tls_t interface. + * Public tnccs_t interface. */ - tls_t public; + tnccs_t public; + + /** + * Server identity + */ + identification_t *server; + + /** + * Client identity + */ + identification_t *peer; /** * Detected TNC IF-TNCCS stack */ tls_t *tls; + + /** + * Underlying TNC IF-T transport protocol + */ + tnc_ift_type_t transport; + + /** + * Type of TNC client authentication + */ + u_int32_t auth_type; + }; /** @@ -66,6 +87,7 @@ METHOD(tls_t, process, status_t, private_tnccs_dynamic_t *this, void *buf, size_t buflen) { tnccs_type_t type; + tnccs_t *tnccs; if (!this->tls) { @@ -76,12 +98,15 @@ METHOD(tls_t, process, status_t, type = determine_tnccs_protocol(*(char*)buf); DBG1(DBG_TNC, "%N protocol detected dynamically", tnccs_type_names, type); - this->tls = (tls_t*)tnc->tnccs->create_instance(tnc->tnccs, type, TRUE); - if (!this->tls) + tnccs = tnc->tnccs->create_instance(tnc->tnccs, type, TRUE, + this->server, this->peer, this->transport); + if (!tnccs) { DBG1(DBG_TNC, "N% protocol not supported", tnccs_type_names, type); return FAILED; } + tnccs->set_auth_type(tnccs, this->auth_type); + this->tls = &tnccs->tls; } return this->tls->process(this->tls, buf, buflen); } @@ -98,6 +123,18 @@ METHOD(tls_t, is_server, bool, return TRUE; } +METHOD(tls_t, get_server_id, identification_t*, + private_tnccs_dynamic_t *this) +{ + return this->server; +} + +METHOD(tls_t, get_peer_id, identification_t*, + private_tnccs_dynamic_t *this) +{ + return this->peer; +} + METHOD(tls_t, get_purpose, tls_purpose_t, private_tnccs_dynamic_t *this) { @@ -120,26 +157,66 @@ METHOD(tls_t, destroy, void, private_tnccs_dynamic_t *this) { DESTROY_IF(this->tls); + this->server->destroy(this->server); + this->peer->destroy(this->peer); free(this); } +METHOD(tnccs_t, get_transport, tnc_ift_type_t, + private_tnccs_dynamic_t *this) +{ + return this->transport; +} + +METHOD(tnccs_t, set_transport, void, + private_tnccs_dynamic_t *this, tnc_ift_type_t transport) +{ + this->transport = transport; +} + +METHOD(tnccs_t, get_auth_type, u_int32_t, + private_tnccs_dynamic_t *this) +{ + return this->auth_type; +} + +METHOD(tnccs_t, set_auth_type, void, + private_tnccs_dynamic_t *this, u_int32_t auth_type) +{ + this->auth_type = auth_type; +} + /** * See header */ -tls_t *tnccs_dynamic_create(bool is_server) +tnccs_t* tnccs_dynamic_create(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport) { private_tnccs_dynamic_t *this; INIT(this, .public = { - .process = _process, - .build = _build, - .is_server = _is_server, - .get_purpose = _get_purpose, - .is_complete = _is_complete, - .get_eap_msk = _get_eap_msk, - .destroy = _destroy, + .tls = { + .process = _process, + .build = _build, + .is_server = _is_server, + .get_server_id = _get_server_id, + .get_peer_id = _get_peer_id, + .get_purpose = _get_purpose, + .is_complete = _is_complete, + .get_eap_msk = _get_eap_msk, + .destroy = _destroy, + }, + .get_transport = _get_transport, + .set_transport = _set_transport, + .get_auth_type = _get_auth_type, + .set_auth_type = _set_auth_type, }, + .server = server->clone(server), + .peer = peer->clone(peer), + .transport = transport, ); return &this->public; diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h index 42410b17f..e4cff74b8 100644 --- a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h +++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Andreas Steffen + * Copyright (C) 2011-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -23,14 +23,20 @@ #include <library.h> -#include <tls.h> +#include <tnc/tnccs/tnccs.h> /** * Create an instance of a dynamic TNC IF-TNCCS protocol handler. * - * @param is_server TRUE to act as TNC Server, FALSE for TNC Client - * @return dynamic TNC IF-TNCCS protocol stack + * @param is_server TRUE to act as TNC Server, FALSE for TNC Client + * @param server Server identity + * @param peer Client identity + * @param transport Underlying IF-T transport protocol + * @return dynamic TNC IF-TNCCS protocol stack */ -tls_t *tnccs_dynamic_create(bool is_server); +tnccs_t* tnccs_dynamic_create(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport); #endif /** TNCCS_DYNAMIC_H_ @}*/ diff --git a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c index 6f581c543..aac57813a 100644 --- a/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c +++ b/src/libcharon/plugins/tnccs_dynamic/tnccs_dynamic_plugin.c @@ -32,8 +32,6 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(CUSTOM, "tnccs-dynamic"), PLUGIN_DEPENDS(CUSTOM, "tnccs-1.1"), PLUGIN_DEPENDS(CUSTOM, "tnccs-2.0"), - PLUGIN_DEPENDS(EAP_SERVER, EAP_TNC), - PLUGIN_DEPENDS(EAP_PEER, EAP_TNC), }; *features = f; return countof(f); @@ -62,4 +60,3 @@ plugin_t *tnccs_dynamic_plugin_create() return &this->plugin; } - diff --git a/src/libcharon/plugins/uci/uci_config.c b/src/libcharon/plugins/uci/uci_config.c index de0bf91af..b58d120c1 100644 --- a/src/libcharon/plugins/uci/uci_config.c +++ b/src/libcharon/plugins/uci/uci_config.c @@ -89,7 +89,7 @@ static traffic_selector_t *create_ts(char *string) { traffic_selector_t *ts; - ts = traffic_selector_create_from_cidr(string, 0, 0); + ts = traffic_selector_create_from_cidr(string, 0, 0, 65535); if (ts) { return ts; @@ -156,7 +156,7 @@ METHOD(enumerator_t, peer_enumerator_enumerate, bool, local_addr, FALSE, charon->socket->get_port(charon->socket, FALSE), remote_addr, FALSE, IKEV2_UDP_PORT, - FRAGMENTATION_NO); + FRAGMENTATION_NO, 0); ike_cfg->add_proposal(ike_cfg, create_proposal(ike_proposal, PROTO_IKE)); this->peer_cfg = peer_cfg_create( name, ike_cfg, CERT_SEND_IF_ASKED, UNIQUE_NO, @@ -255,7 +255,7 @@ METHOD(enumerator_t, ike_enumerator_enumerate, bool, local_addr, FALSE, charon->socket->get_port(charon->socket, FALSE), remote_addr, FALSE, IKEV2_UDP_PORT, - FRAGMENTATION_NO); + FRAGMENTATION_NO, 0); this->ike_cfg->add_proposal(this->ike_cfg, create_proposal(ike_proposal, PROTO_IKE)); @@ -343,4 +343,3 @@ uci_config_t *uci_config_create(uci_parser_t *parser) return &this->public; } - diff --git a/src/libcharon/plugins/unity/unity_handler.c b/src/libcharon/plugins/unity/unity_handler.c index 31d13add2..9d145b93f 100644 --- a/src/libcharon/plugins/unity/unity_handler.c +++ b/src/libcharon/plugins/unity/unity_handler.c @@ -174,7 +174,6 @@ static job_requeue_t add_exclude_async(entry_t *entry) ike_sa_t *ike_sa; char name[128]; host_t *host; - bool has_vip = FALSE; ike_sa = charon->ike_sa_manager->checkout_by_id(charon->ike_sa_manager, entry->sa, FALSE); @@ -187,23 +186,21 @@ static job_requeue_t add_exclude_async(entry_t *entry) FALSE, 0, 0, NULL, NULL, FALSE); child_cfg->add_traffic_selector(child_cfg, FALSE, entry->ts->clone(entry->ts)); + host = ike_sa->get_my_host(ike_sa); + child_cfg->add_traffic_selector(child_cfg, TRUE, + traffic_selector_create_from_subnet(host->clone(host), + 32, 0, 0, 65535)); + charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); + enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE); while (enumerator->enumerate(enumerator, &host)) { - has_vip = TRUE; child_cfg->add_traffic_selector(child_cfg, TRUE, - traffic_selector_create_from_subnet(host->clone(host), 32, 0, 0)); + traffic_selector_create_from_subnet(host->clone(host), + 32, 0, 0, 65535)); } enumerator->destroy(enumerator); - if (!has_vip) - { - host = ike_sa->get_my_host(ike_sa); - child_cfg->add_traffic_selector(child_cfg, TRUE, - traffic_selector_create_from_subnet(host->clone(host), 32, 0, 0)); - } - charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa); - charon->shunts->install(charon->shunts, child_cfg); child_cfg->destroy(child_cfg); diff --git a/src/libcharon/sa/eap/eap_inner_method.h b/src/libcharon/sa/eap/eap_inner_method.h new file mode 100644 index 000000000..500852965 --- /dev/null +++ b/src/libcharon/sa/eap/eap_inner_method.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2013 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 eap_inner_method eap_inner_method + * @{ @ingroup eap + */ + +#ifndef EAP_INNER_METHOD_H_ +#define EAP_INNER_METHOD_H_ + +typedef struct eap_inner_method_t eap_inner_method_t; + +#include <library.h> + +#include "eap_method.h" + +/** + * Interface of a weak inner EAP method like EAP-TNC or PT-EAP + * that must be encapsulated in a strong TLS-based EAP method + */ +struct eap_inner_method_t { + + /* + * Public EAP method interface + */ + eap_method_t eap_method; + + /* + * Get type of outer EAP authentication method + * + * @return outer EAP authentication type + */ + eap_type_t (*get_auth_type)(eap_inner_method_t *this); + + /* + * Set type of outer EAP Client/Server authentication + * + * @param type outer EAP authentication type + */ + void (*set_auth_type)(eap_inner_method_t *this, eap_type_t type); + +}; + +#endif /** EAP_INNER_METHOD_H_ @}*/ diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c index 4029db11d..0157599c1 100644 --- a/src/libcharon/sa/ike_sa.c +++ b/src/libcharon/sa/ike_sa.c @@ -900,7 +900,7 @@ METHOD(ike_sa_t, update_hosts, void, else { /* update our address in any case */ - if (!me->equals(me, this->my_host)) + if (force && !me->equals(me, this->my_host)) { set_my_host(this, me->clone(me)); update = TRUE; @@ -909,7 +909,8 @@ METHOD(ike_sa_t, update_hosts, void, if (!other->equals(other, this->other_host)) { /* update others address if we are NOT NATed */ - if (force || !has_condition(this, COND_NAT_HERE)) + if ((has_condition(this, COND_NAT_THERE) && + !has_condition(this, COND_NAT_HERE)) || force ) { set_other_host(this, other->clone(other)); update = TRUE; @@ -939,14 +940,38 @@ METHOD(ike_sa_t, update_hosts, void, } } +/** + * Set configured DSCP value on packet + */ +static void set_dscp(private_ike_sa_t *this, packet_t *packet) +{ + ike_cfg_t *ike_cfg; + + /* prefer IKE config on peer_cfg, as its selection is more accurate + * then the initial IKE config */ + if (this->peer_cfg) + { + ike_cfg = this->peer_cfg->get_ike_cfg(this->peer_cfg); + } + else + { + ike_cfg = this->ike_cfg; + } + if (ike_cfg) + { + packet->set_dscp(packet, ike_cfg->get_dscp(ike_cfg)); + } +} + METHOD(ike_sa_t, generate_message, status_t, private_ike_sa_t *this, message_t *message, packet_t **packet) { status_t status; if (message->is_encoded(message)) - { /* already done */ + { /* already encoded in task, but set DSCP value */ *packet = message->get_packet(message); + set_dscp(this, *packet); return SUCCESS; } this->stats[STAT_OUTBOUND] = time_monotonic(NULL); @@ -955,6 +980,7 @@ METHOD(ike_sa_t, generate_message, status_t, status = message->generate(message, this->keymat, packet); if (status == SUCCESS) { + set_dscp(this, *packet); charon->bus->message(charon->bus, message, FALSE, FALSE); } return status; @@ -1225,24 +1251,6 @@ METHOD(ike_sa_t, process_message, status_t, { /* do not handle messages in passive state */ return FAILED; } - switch (message->get_exchange_type(message)) - { - case ID_PROT: - case AGGRESSIVE: - case IKE_SA_INIT: - case IKE_AUTH: - if (this->state != IKE_CREATED && - this->state != IKE_CONNECTING && - message->get_first_payload_type(message) != FRAGMENT_V1) - { - DBG1(DBG_IKE, "ignoring %N in established IKE_SA state", - exchange_type_names, message->get_exchange_type(message)); - return FAILED; - } - break; - default: - break; - } if (message->get_major_version(message) != this->version) { DBG1(DBG_IKE, "ignoring %N IKEv%u exchange on %N SA", diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c index 2ac8c3123..4fbc4da8e 100644 --- a/src/libcharon/sa/ike_sa_manager.c +++ b/src/libcharon/sa/ike_sa_manager.c @@ -108,9 +108,9 @@ struct entry_t { identification_t *other_id; /** - * message ID currently processing, if any + * message ID or hash of currently processing message, -1 if none */ - u_int32_t message_id; + u_int32_t processing; }; /** @@ -135,23 +135,12 @@ static status_t entry_destroy(entry_t *this) */ static entry_t *entry_create() { - entry_t *this = malloc_thing(entry_t); - - this->waiting_threads = 0; - this->condvar = condvar_create(CONDVAR_TYPE_DEFAULT); - - /* we set checkout flag when we really give it out */ - this->checked_out = FALSE; - this->driveout_new_threads = FALSE; - this->driveout_waiting_threads = FALSE; - this->message_id = -1; - this->init_hash = chunk_empty; - this->other = NULL; - this->half_open = FALSE; - this->my_id = NULL; - this->other_id = NULL; - this->ike_sa_id = NULL; - this->ike_sa = NULL; + entry_t *this; + + INIT(this, + .condvar = condvar_create(CONDVAR_TYPE_DEFAULT), + .processing = -1, + ); return this; } @@ -1171,6 +1160,20 @@ METHOD(ike_sa_manager_t, checkout_new, ike_sa_t*, return ike_sa; } +/** + * Get the message ID or message hash to detect early retransmissions + */ +static u_int32_t get_message_id_or_hash(message_t *message) +{ + /* Use the message ID, or the message hash in IKEv1 Main/Aggressive mode */ + if (message->get_major_version(message) == IKEV1_MAJOR_VERSION && + message->get_message_id(message) == 0) + { + return chunk_hash(message->get_packet_data(message)); + } + return message->get_message_id(message); +} + METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, private_ike_sa_manager_t* this, message_t *message) { @@ -1246,7 +1249,7 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, entry->checked_out = TRUE; unlock_single_segment(this, segment); - entry->message_id = message->get_message_id(message); + entry->processing = get_message_id_or_hash(message); entry->init_hash = hash; DBG2(DBG_MGR, "created IKE_SA %s[%u]", @@ -1290,12 +1293,11 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, if (get_entry_by_id(this, id, &entry, &segment) == SUCCESS) { - /* only check out in IKEv2 if we are not already processing it */ - if (message->get_request(message) && - message->get_message_id(message) == entry->message_id) + /* only check out if we are not already processing it. */ + if (entry->processing == get_message_id_or_hash(message)) { DBG1(DBG_MGR, "ignoring request with ID %u, already processing", - entry->message_id); + entry->processing); } else if (wait_for_entry(this, entry, segment)) { @@ -1305,7 +1307,7 @@ METHOD(ike_sa_manager_t, checkout_by_message, ike_sa_t*, entry->checked_out = TRUE; if (message->get_first_payload_type(message) != FRAGMENT_V1) { - entry->message_id = message->get_message_id(message); + entry->processing = get_message_id_or_hash(message); } if (ike_id->get_responder_spi(ike_id) == 0) { @@ -1564,7 +1566,7 @@ METHOD(ike_sa_manager_t, checkin, void, entry->ike_sa_id->replace_values(entry->ike_sa_id, ike_sa->get_id(ike_sa)); /* signal waiting threads */ entry->checked_out = FALSE; - entry->message_id = -1; + entry->processing = -1; /* check if this SA is half-open */ if (entry->half_open && ike_sa->get_state(ike_sa) != IKE_CONNECTING) { @@ -1745,6 +1747,23 @@ METHOD(ike_sa_manager_t, create_id_enumerator, enumerator_t*, (void*)id_enumerator_cleanup, ids); } +/** + * Move all CHILD_SAs from old to new + */ +static void adopt_children(ike_sa_t *old, ike_sa_t *new) +{ + enumerator_t *enumerator; + child_sa_t *child_sa; + + enumerator = old->create_child_sa_enumerator(old); + while (enumerator->enumerate(enumerator, &child_sa)) + { + old->remove_child_sa(old, enumerator); + new->add_child_sa(new, child_sa); + } + enumerator->destroy(enumerator); +} + METHOD(ike_sa_manager_t, check_uniqueness, bool, private_ike_sa_manager_t *this, ike_sa_t *ike_sa, bool force_replace) { @@ -1782,6 +1801,7 @@ METHOD(ike_sa_manager_t, check_uniqueness, bool, { DBG1(DBG_IKE, "destroying duplicate IKE_SA for peer '%Y', " "received INITIAL_CONTACT", other); + charon->bus->ike_updown(charon->bus, duplicate, FALSE); checkin_and_destroy(this, duplicate); continue; } @@ -1796,6 +1816,10 @@ METHOD(ike_sa_manager_t, check_uniqueness, bool, { case UNIQUE_REPLACE: charon->bus->alert(charon->bus, ALERT_UNIQUE_REPLACE); + if (duplicate->get_version(duplicate) == IKEV1) + { + adopt_children(duplicate, ike_sa); + } DBG1(DBG_IKE, "deleting duplicate IKE_SA for peer " "'%Y' due to uniqueness policy", other); status = duplicate->delete(duplicate); diff --git a/src/libcharon/sa/ikev1/keymat_v1.c b/src/libcharon/sa/ikev1/keymat_v1.c index eb642109b..39e4cad20 100644 --- a/src/libcharon/sa/ikev1/keymat_v1.c +++ b/src/libcharon/sa/ikev1/keymat_v1.c @@ -431,6 +431,7 @@ METHOD(keymat_v1_t, derive_ike_keys, bool, { case AUTH_PSK: case AUTH_XAUTH_INIT_PSK: + case AUTH_XAUTH_RESP_PSK: { /* SKEYID = prf(pre-shared-key, Ni_b | Nr_b) */ chunk_t psk; if (!shared_key) diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c index 8a4761d5c..ac3b8d0dc 100644 --- a/src/libcharon/sa/ikev1/task_manager_v1.c +++ b/src/libcharon/sa/ikev1/task_manager_v1.c @@ -1163,6 +1163,15 @@ static status_t process_response(private_task_manager_t *this, if (message->get_exchange_type(message) != this->initiating.type) { + /* Windows server sends a fourth quick mode message having an initial + * contact notify. Ignore this message for compatibility. */ + if (this->initiating.type == EXCHANGE_TYPE_UNDEFINED && + message->get_exchange_type(message) == QUICK_MODE && + message->get_notify(message, INITIAL_CONTACT)) + { + DBG1(DBG_IKE, "ignoring fourth Quick Mode message"); + return SUCCESS; + } DBG1(DBG_IKE, "received %N response, but expected %N", exchange_type_names, message->get_exchange_type(message), exchange_type_names, this->initiating.type); @@ -1471,6 +1480,21 @@ METHOD(task_manager_t, process_message, status_t, charon->bus->alert(charon->bus, ALERT_RETRANSMIT_RECEIVE, msg); return SUCCESS; } + + /* reject Main/Agressive Modes once established */ + if (msg->get_exchange_type(msg) == ID_PROT || + msg->get_exchange_type(msg) == AGGRESSIVE) + { + if (this->ike_sa->get_state(this->ike_sa) != IKE_CREATED && + this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING && + msg->get_first_payload_type(msg) != FRAGMENT_V1) + { + DBG1(DBG_IKE, "ignoring %N in established IKE_SA state", + exchange_type_names, msg->get_exchange_type(msg)); + return FAILED; + } + } + if (msg->get_exchange_type(msg) == TRANSACTION && this->active_tasks->get_count(this->active_tasks)) { /* main mode not yet complete, queue XAuth/Mode config tasks */ @@ -2030,4 +2054,3 @@ task_manager_v1_t *task_manager_v1_create(ike_sa_t *ike_sa) return &this->public; } - diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c index 1eae6aa93..afdff8cf9 100644 --- a/src/libcharon/sa/ikev1/tasks/quick_mode.c +++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c @@ -576,12 +576,12 @@ static bool get_ts(private_quick_mode_t *this, message_t *message) if (!tsi) { tsi = traffic_selector_create_from_subnet(hsi->clone(hsi), - hsi->get_family(hsi) == AF_INET ? 32 : 128, 0, 0); + hsi->get_family(hsi) == AF_INET ? 32 : 128, 0, 0, 65535); } if (!tsr) { tsr = traffic_selector_create_from_subnet(hsr->clone(hsr), - hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0); + hsr->get_family(hsr) == AF_INET ? 32 : 128, 0, 0, 65535); } if (this->mode == MODE_TRANSPORT && this->udp && (!tsi->is_host(tsi, hsi) || !tsr->is_host(tsr, hsr))) @@ -594,20 +594,27 @@ static bool get_ts(private_quick_mode_t *this, message_t *message) if (this->initiator) { + traffic_selector_t *tsisub, *tsrsub; + /* check if peer selection is valid */ - if (!tsr->is_contained_in(tsr, this->tsr) || - !tsi->is_contained_in(tsi, this->tsi)) + tsisub = this->tsi->get_subset(this->tsi, tsi); + tsrsub = this->tsr->get_subset(this->tsr, tsr); + if (!tsisub || !tsrsub) { DBG1(DBG_IKE, "peer selected invalid traffic selectors: " "%R for %R, %R for %R", tsi, this->tsi, tsr, this->tsr); + DESTROY_IF(tsisub); + DESTROY_IF(tsrsub); tsi->destroy(tsi); tsr->destroy(tsr); return FALSE; } + tsi->destroy(tsi); + tsr->destroy(tsr); this->tsi->destroy(this->tsi); this->tsr->destroy(this->tsr); - this->tsi = tsi; - this->tsr = tsr; + this->tsi = tsisub; + this->tsr = tsrsub; } else { diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c index aa0644033..b8359cc88 100644 --- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c +++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c @@ -667,6 +667,16 @@ METHOD(authenticator_t, build_client, status_t, METHOD(authenticator_t, is_mutual, bool, private_eap_authenticator_t *this) { + if (this->method) + { + u_int32_t vendor; + + if (this->method->get_type(this->method, &vendor) != EAP_IDENTITY || + vendor != 0) + { + return this->method->is_mutual(this->method); + } + } /* we don't know yet, but insist on it after EAP is complete */ this->require_mutual = TRUE; return TRUE; diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c index ea0117c54..a53c06bf7 100644 --- a/src/libcharon/sa/ikev2/task_manager_v2.c +++ b/src/libcharon/sa/ikev2/task_manager_v2.c @@ -1123,6 +1123,18 @@ METHOD(task_manager_t, process_message, status_t, { if (mid == this->responding.mid) { + /* reject initial messages once established */ + if (msg->get_exchange_type(msg) == IKE_SA_INIT || + msg->get_exchange_type(msg) == IKE_AUTH) + { + if (this->ike_sa->get_state(this->ike_sa) != IKE_CREATED && + this->ike_sa->get_state(this->ike_sa) != IKE_CONNECTING) + { + DBG1(DBG_IKE, "ignoring %N in established IKE_SA state", + exchange_type_names, msg->get_exchange_type(msg)); + return FAILED; + } + } if (this->ike_sa->get_state(this->ike_sa) == IKE_CREATED || this->ike_sa->get_state(this->ike_sa) == IKE_CONNECTING || msg->get_exchange_type(msg) != IKE_SA_INIT) @@ -1163,6 +1175,10 @@ METHOD(task_manager_t, process_message, status_t, { DBG1(DBG_IKE, "received message ID %d, expected %d. Ignored", mid, this->responding.mid); + if (msg->get_exchange_type(msg) == IKE_SA_INIT) + { /* clean up IKE_SA state if IKE_SA_INIT has invalid msg ID */ + return DESTROY_ME; + } } } else diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c index eb3972c29..32c0e8c4a 100644 --- a/src/libcharon/sa/ikev2/tasks/child_create.c +++ b/src/libcharon/sa/ikev2/tasks/child_create.c @@ -18,6 +18,7 @@ #include "child_create.h" #include <daemon.h> +#include <hydra.h> #include <sa/ikev2/keymat_v2.h> #include <crypto/diffie_hellman.h> #include <credentials/certificates/x509.h> @@ -615,6 +616,7 @@ static void build_payloads(private_child_create_t *this, message_t *message) nonce_payload_t *nonce_payload; ke_payload_t *ke_payload; ts_payload_t *ts_payload; + kernel_feature_t features; /* add SA payload */ if (this->initiator) @@ -661,6 +663,13 @@ static void build_payloads(private_child_create_t *this, message_t *message) default: break; } + + features = hydra->kernel_interface->get_features(hydra->kernel_interface); + if (!(features & KERNEL_ESP_V3_TFC)) + { + message->add_notify(message, FALSE, ESP_TFC_PADDING_NOT_SUPPORTED, + chunk_empty); + } } /** diff --git a/src/libcharon/sa/ikev2/tasks/ike_auth.c b/src/libcharon/sa/ikev2/tasks/ike_auth.c index 70efcd7af..942f97cf5 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_auth.c +++ b/src/libcharon/sa/ikev2/tasks/ike_auth.c @@ -223,6 +223,18 @@ static auth_cfg_t *get_auth_cfg(private_ike_auth_t *this, bool local) } /** + * Move the currently active auth config to the auth configs completed + */ +static void apply_auth_cfg(private_ike_auth_t *this, bool local) +{ + auth_cfg_t *cfg; + + cfg = auth_cfg_create(); + cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, local), local); + this->ike_sa->add_auth_cfg(this->ike_sa, local, cfg); +} + +/** * Check if we have should initiate another authentication round */ static bool do_another_auth(private_ike_auth_t *this) @@ -307,7 +319,7 @@ static bool update_cfg_candidates(private_ike_auth_t *this, bool strict) { if (this->peer_cfg) { - bool complies = TRUE; + char *comply_error = NULL; enumerator_t *e1, *e2, *tmp; auth_cfg_t *c1, *c2; @@ -324,22 +336,30 @@ static bool update_cfg_candidates(private_ike_auth_t *this, bool strict) while (e1->enumerate(e1, &c1)) { /* check if done authentications comply to configured ones */ - if ((!e2->enumerate(e2, &c2)) || - (!strict && !c1->complies(c1, c2, TRUE)) || - (strict && !c2->complies(c2, c1, TRUE))) + if (!e2->enumerate(e2, &c2)) + { + comply_error = "insufficient authentication rounds"; + break; + } + if (!strict && !c1->complies(c1, c2, TRUE)) { - complies = FALSE; + comply_error = "non-matching authentication done"; + break; + } + if (strict && !c2->complies(c2, c1, TRUE)) + { + comply_error = "constraint checking failed"; break; } } e1->destroy(e1); e2->destroy(e2); - if (complies) + if (!comply_error) { break; } - DBG1(DBG_CFG, "selected peer config '%s' inacceptable", - this->peer_cfg->get_name(this->peer_cfg)); + DBG1(DBG_CFG, "selected peer config '%s' inacceptable: %s", + this->peer_cfg->get_name(this->peer_cfg), comply_error); this->peer_cfg->destroy(this->peer_cfg); } if (this->candidates->remove_first(this->candidates, @@ -464,10 +484,7 @@ METHOD(task_t, build_i, status_t, switch (this->my_auth->build(this->my_auth, message)) { case SUCCESS: - /* authentication step complete, reset authenticator */ - cfg = auth_cfg_create(); - cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE), TRUE); - this->ike_sa->add_auth_cfg(this->ike_sa, TRUE, cfg); + apply_auth_cfg(this, TRUE); this->my_auth->destroy(this->my_auth); this->my_auth = NULL; break; @@ -640,10 +657,7 @@ METHOD(task_t, process_r, status_t, return NEED_MORE; } - /* store authentication information */ - cfg = auth_cfg_create(); - cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE); - this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg); + apply_auth_cfg(this, FALSE); if (!update_cfg_candidates(this, FALSE)) { @@ -778,10 +792,7 @@ METHOD(task_t, build_r, status_t, switch (this->my_auth->build(this->my_auth, message)) { case SUCCESS: - cfg = auth_cfg_create(); - cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE), - TRUE); - this->ike_sa->add_auth_cfg(this->ike_sa, TRUE, cfg); + apply_auth_cfg(this, TRUE); this->my_auth->destroy(this->my_auth); this->my_auth = NULL; break; @@ -969,10 +980,10 @@ METHOD(task_t, process_i, status_t, goto peer_auth_failed; } - /* store authentication information, reset authenticator */ - cfg = auth_cfg_create(); - cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, FALSE), FALSE); - this->ike_sa->add_auth_cfg(this->ike_sa, FALSE, cfg); + if (!mutual_eap) + { + apply_auth_cfg(this, FALSE); + } } if (this->my_auth) @@ -980,10 +991,11 @@ METHOD(task_t, process_i, status_t, switch (this->my_auth->process(this->my_auth, message)) { case SUCCESS: - cfg = auth_cfg_create(); - cfg->merge(cfg, this->ike_sa->get_auth_cfg(this->ike_sa, TRUE), - TRUE); - this->ike_sa->add_auth_cfg(this->ike_sa, TRUE, cfg); + apply_auth_cfg(this, TRUE); + if (this->my_auth->is_mutual(this->my_auth)) + { + apply_auth_cfg(this, FALSE); + } this->my_auth->destroy(this->my_auth); this->my_auth = NULL; this->do_another_auth = do_another_auth(this); diff --git a/src/libcharon/sa/ikev2/tasks/ike_dpd.c b/src/libcharon/sa/ikev2/tasks/ike_dpd.c index 28ccc2efe..7a33f7938 100644 --- a/src/libcharon/sa/ikev2/tasks/ike_dpd.c +++ b/src/libcharon/sa/ikev2/tasks/ike_dpd.c @@ -37,12 +37,6 @@ METHOD(task_t, return_need_more, status_t, return NEED_MORE; } -METHOD(task_t, return_success, status_t, - private_ike_dpd_t *this, message_t *message) -{ - return SUCCESS; -} - METHOD(task_t, get_type, task_type_t, private_ike_dpd_t *this) { @@ -82,11 +76,11 @@ ike_dpd_t *ike_dpd_create(bool initiator) if (initiator) { this->public.task.build = _return_need_more; - this->public.task.process = _return_success; + this->public.task.process = (void*)return_success; } else { - this->public.task.build = _return_success; + this->public.task.build = (void*)return_success; this->public.task.process = _return_need_more; } diff --git a/src/libfast/controller.h b/src/libfast/controller.h index 1edf72e90..7a7efc706 100644 --- a/src/libfast/controller.h +++ b/src/libfast/controller.h @@ -14,7 +14,7 @@ */ /** - * @defgroup controller_i controller + * @defgroup controller controller * @{ @ingroup libfast */ diff --git a/src/libhydra/attributes/mem_pool.c b/src/libhydra/attributes/mem_pool.c index af53e10de..c82b1d02f 100644 --- a/src/libhydra/attributes/mem_pool.c +++ b/src/libhydra/attributes/mem_pool.c @@ -21,7 +21,7 @@ #include <collections/linked_list.h> #include <threading/mutex.h> -#define POOL_LIMIT (sizeof(uintptr_t)*8) +#define POOL_LIMIT (sizeof(u_int)*8 - 1) typedef struct private_mem_pool_t private_mem_pool_t; @@ -513,12 +513,11 @@ METHOD(mem_pool_t, destroy, void, } /** - * Described in header + * Generic constructor */ -mem_pool_t *mem_pool_create(char *name, host_t *base, int bits) +static private_mem_pool_t *create_generic(char *name) { private_mem_pool_t *this; - int addr_bits; INIT(this, .public = { @@ -538,6 +537,18 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits) .mutex = mutex_create(MUTEX_TYPE_DEFAULT), ); + return this; +} + +/** + * Described in header + */ +mem_pool_t *mem_pool_create(char *name, host_t *base, int bits) +{ + private_mem_pool_t *this; + int addr_bits; + + this = create_generic(name); if (base) { addr_bits = base->get_family(base) == AF_INET ? 32 : 128; @@ -550,7 +561,7 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits) DBG1(DBG_CFG, "virtual IP pool too large, limiting to %H/%d", base, addr_bits - bits); } - this->size = 1 << (bits); + this->size = 1 << bits; if (this->size > 2) { /* do not use first and last addresses of a block */ @@ -563,3 +574,37 @@ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits) return &this->public; } +/** + * Described in header + */ +mem_pool_t *mem_pool_create_range(char *name, host_t *from, host_t *to) +{ + private_mem_pool_t *this; + chunk_t fromaddr, toaddr; + u_int32_t diff; + + fromaddr = from->get_address(from); + toaddr = to->get_address(to); + + if (from->get_family(from) != to->get_family(to) || + fromaddr.len != toaddr.len || fromaddr.len < sizeof(diff) || + memcmp(fromaddr.ptr, toaddr.ptr, toaddr.len) > 0) + { + DBG1(DBG_CFG, "invalid IP address range: %H-%H", from, to); + return NULL; + } + if (fromaddr.len > sizeof(diff) && + !chunk_equals(chunk_create(fromaddr.ptr, fromaddr.len - sizeof(diff)), + chunk_create(toaddr.ptr, toaddr.len - sizeof(diff)))) + { + DBG1(DBG_CFG, "IP address range too large: %H-%H", from, to); + return NULL; + } + this = create_generic(name); + this->base = from->clone(from); + diff = untoh32(toaddr.ptr + toaddr.len - sizeof(diff)) - + untoh32(fromaddr.ptr + fromaddr.len - sizeof(diff)); + this->size = diff + 1; + + return &this->public; +} diff --git a/src/libhydra/attributes/mem_pool.h b/src/libhydra/attributes/mem_pool.h index 692885ecd..7347bb547 100644 --- a/src/libhydra/attributes/mem_pool.h +++ b/src/libhydra/attributes/mem_pool.h @@ -89,7 +89,7 @@ struct mem_pool_t { * * @param id the id to acquire an address for * @param requested acquire this address, if possible - * @param existing TRUE to look for an existing lease, FALSE for a new one + * @param operation acquire operation to perform, see above * @return the acquired address */ host_t* (*acquire_address)(mem_pool_t *this, identification_t *id, @@ -128,9 +128,19 @@ struct mem_pool_t { * * @param name name of this pool * @param base base address of this pool, NULL to create an empty pool - * @param bits net mask + * @param bits number of non-network bits in base, as in CIDR notation + * @return memory pool instance */ mem_pool_t *mem_pool_create(char *name, host_t *base, int bits); -#endif /** MEM_POOL_H_ @} */ +/** + * Create an in-memory IP address from a range. + * + * @param name name of this pool + * @param from start of ranged pool + * @param to end of ranged pool + * @return memory pool instance, NULL if range invalid + */ +mem_pool_t *mem_pool_create_range(char *name, host_t *from, host_t *to); +#endif /** MEM_POOL_H_ @} */ diff --git a/src/libhydra/kernel/kernel_interface.c b/src/libhydra/kernel/kernel_interface.c index 8948e0561..b82fd6d3d 100644 --- a/src/libhydra/kernel/kernel_interface.c +++ b/src/libhydra/kernel/kernel_interface.c @@ -137,6 +137,22 @@ struct private_kernel_interface_t { bool ifaces_exclude; }; +METHOD(kernel_interface_t, get_features, kernel_feature_t, + private_kernel_interface_t *this) +{ + kernel_feature_t features = 0; + + if (this->ipsec && this->ipsec->get_features) + { + features |= this->ipsec->get_features(this->ipsec); + } + if (this->net && this->net->get_features) + { + features |= this->net->get_features(this->net); + } + return features; +} + METHOD(kernel_interface_t, get_spi, status_t, private_kernel_interface_t *this, host_t *src, host_t *dst, u_int8_t protocol, u_int32_t reqid, u_int32_t *spi) @@ -682,6 +698,7 @@ kernel_interface_t *kernel_interface_create() INIT(this, .public = { + .get_features = _get_features, .get_spi = _get_spi, .get_cpi = _get_cpi, .add_sa = _add_sa, @@ -757,4 +774,3 @@ kernel_interface_t *kernel_interface_create() return &this->public; } - diff --git a/src/libhydra/kernel/kernel_interface.h b/src/libhydra/kernel/kernel_interface.h index 8d8ef2e83..8d8d048d0 100644 --- a/src/libhydra/kernel/kernel_interface.h +++ b/src/libhydra/kernel/kernel_interface.h @@ -47,6 +47,7 @@ #define KERNEL_INTERFACE_H_ typedef struct kernel_interface_t kernel_interface_t; +typedef enum kernel_feature_t kernel_feature_t; #include <networking/host.h> #include <crypto/prf_plus.h> @@ -56,6 +57,17 @@ typedef struct kernel_interface_t kernel_interface_t; #include <kernel/kernel_net.h> /** + * Bitfield of optional features a kernel backend supports. + * + * This feature-set is for both, kernel_ipsec_t and kernel_net_t. Each + * backend returns a subset of these features. + */ +enum kernel_feature_t { + /** IPsec can process ESPv3 (RFC 4303) TFC padded packets */ + KERNEL_ESP_V3_TFC = (1<<0), +}; + +/** * Constructor function for ipsec kernel interface */ typedef kernel_ipsec_t* (*kernel_ipsec_constructor_t)(void); @@ -74,6 +86,13 @@ typedef kernel_net_t* (*kernel_net_constructor_t)(void); struct kernel_interface_t { /** + * Get the feature set supported by the net and ipsec kernel backends. + * + * @return ORed feature-set of backends + */ + kernel_feature_t (*get_features)(kernel_interface_t *this); + + /** * Get a SPI from the kernel. * * @param src source address of SA diff --git a/src/libhydra/kernel/kernel_ipsec.h b/src/libhydra/kernel/kernel_ipsec.h index 1da0805cb..c8afcaffd 100644 --- a/src/libhydra/kernel/kernel_ipsec.h +++ b/src/libhydra/kernel/kernel_ipsec.h @@ -30,6 +30,7 @@ typedef struct kernel_ipsec_t kernel_ipsec_t; #include <ipsec/ipsec_types.h> #include <selectors/traffic_selector.h> #include <plugins/plugin.h> +#include <kernel/kernel_interface.h> /** * Interface to the ipsec subsystem of the kernel. @@ -45,6 +46,13 @@ typedef struct kernel_ipsec_t kernel_ipsec_t; struct kernel_ipsec_t { /** + * Get the feature set supported by this kernel backend. + * + * @return ORed feature-set of backend + */ + kernel_feature_t (*get_features)(kernel_ipsec_t *this); + + /** * Get a SPI from the kernel. * * @param src source address of SA diff --git a/src/libhydra/kernel/kernel_net.h b/src/libhydra/kernel/kernel_net.h index 6a3b2cee7..0d3417f1d 100644 --- a/src/libhydra/kernel/kernel_net.h +++ b/src/libhydra/kernel/kernel_net.h @@ -28,6 +28,7 @@ typedef enum kernel_address_type_t kernel_address_type_t; #include <collections/enumerator.h> #include <networking/host.h> #include <plugins/plugin.h> +#include <kernel/kernel_interface.h> /** * Type of addresses (e.g. when enumerating them) @@ -56,6 +57,13 @@ enum kernel_address_type_t { struct kernel_net_t { /** + * Get the feature set supported by this kernel backend. + * + * @return ORed feature-set of backend + */ + kernel_feature_t (*get_features)(kernel_net_t *this); + + /** * Get our outgoing source address for a destination. * * Does a route lookup to get the source address used to reach dest. diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c index f9b2634a0..3e84d1699 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -95,12 +95,6 @@ #define XFRM_RTA(nlh, x) ((struct rtattr*)(NLMSG_DATA(nlh) + \ NLMSG_ALIGN(sizeof(x)))) /** - * Returns a pointer to the next rtattr following rta. - * !!! Do not use this to parse messages. Use RTA_NEXT and RTA_OK instead !!! - */ -#define XFRM_RTA_NEXT(rta) ((struct rtattr*)(((char*)(rta)) + \ - RTA_ALIGN((rta)->rta_len))) -/** * Returns the total size of attached rta data * (after 'usual' netlink data x like 'struct xfrm_usersa_info') */ @@ -176,8 +170,6 @@ ENUM(xfrm_attr_type_names, XFRMA_UNSPEC, XFRMA_REPLAY_ESN_VAL, "XFRMA_REPLAY_ESN_VAL", ); -#define END_OF_LIST -1 - /** * Algorithms for encryption */ @@ -208,7 +200,6 @@ static kernel_algorithm_t encryption_algs[] = { /* {ENCR_CAMELLIA_CCM_ICV16, "***" }, */ {ENCR_SERPENT_CBC, "serpent" }, {ENCR_TWOFISH_CBC, "twofish" }, - {END_OF_LIST, NULL } }; /** @@ -226,7 +217,6 @@ static kernel_algorithm_t integrity_algs[] = { /* {AUTH_DES_MAC, "***" }, */ /* {AUTH_KPDK_MD5, "***" }, */ {AUTH_AES_XCBC_96, "xcbc(aes)" }, - {END_OF_LIST, NULL } }; /** @@ -237,7 +227,6 @@ static kernel_algorithm_t compression_algs[] = { {IPCOMP_DEFLATE, "deflate" }, {IPCOMP_LZS, "lzs" }, {IPCOMP_LZJH, "lzjh" }, - {END_OF_LIST, NULL } }; /** @@ -246,33 +235,39 @@ static kernel_algorithm_t compression_algs[] = { static char* lookup_algorithm(transform_type_t type, int ikev2) { kernel_algorithm_t *list; - char *name = NULL; + int i, count; + char *name; switch (type) { case ENCRYPTION_ALGORITHM: list = encryption_algs; + count = countof(encryption_algs); break; case INTEGRITY_ALGORITHM: list = integrity_algs; + count = countof(integrity_algs); break; case COMPRESSION_ALGORITHM: list = compression_algs; + count = countof(compression_algs); break; default: return NULL; } - while (list->ikev2 != END_OF_LIST) + for (i = 0; i < count; i++) { - if (list->ikev2 == ikev2) + if (list[i].ikev2 == ikev2) { - return list->name; + return list[i].name; } - list++; } - hydra->kernel_interface->lookup_algorithm(hydra->kernel_interface, ikev2, - type, NULL, &name); - return name; + if (hydra->kernel_interface->lookup_algorithm(hydra->kernel_interface, + ikev2, type, NULL, &name)) + { + return name; + } + return NULL; } typedef struct private_kernel_netlink_ipsec_t private_kernel_netlink_ipsec_t; @@ -787,7 +782,7 @@ static traffic_selector_t* selector2ts(struct xfrm_selector *sel, bool src) if (host) { return traffic_selector_create_from_subnet(host, prefixlen, - sel->proto, port); + sel->proto, port, port ?: 65535); } return NULL; } @@ -1036,6 +1031,12 @@ static job_requeue_t receive_events(private_kernel_netlink_ipsec_t *this) return JOB_REQUEUE_DIRECT; } +METHOD(kernel_ipsec_t, get_features, kernel_feature_t, + private_kernel_netlink_ipsec_t *this) +{ + return KERNEL_ESP_V3_TFC; +} + /** * Get an SPI for a specific protocol from the kernel. */ @@ -1144,6 +1145,26 @@ METHOD(kernel_ipsec_t, get_cpi, status_t, return SUCCESS; } +/** + * Add a XFRM mark to message if required + */ +static bool add_mark(struct nlmsghdr *hdr, int buflen, mark_t mark) +{ + if (mark.value) + { + struct xfrm_mark *xmrk; + + xmrk = netlink_reserve(hdr, buflen, XFRMA_MARK, sizeof(*xmrk)); + if (!xmrk) + { + return FALSE; + } + xmrk->v = mark.value; + xmrk->m = mark.mask; + } + return TRUE; +} + METHOD(kernel_ipsec_t, add_sa, status_t, private_kernel_netlink_ipsec_t *this, host_t *src, host_t *dst, u_int32_t spi, u_int8_t protocol, u_int32_t reqid, mark_t mark, @@ -1216,8 +1237,6 @@ METHOD(kernel_ipsec_t, add_sa, status_t, sa->lft.soft_use_expires_seconds = 0; sa->lft.hard_use_expires_seconds = 0; - struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_info); - switch (enc_alg) { case ENCR_UNDEFINED: @@ -1250,23 +1269,17 @@ METHOD(kernel_ipsec_t, add_sa, status_t, DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", encryption_algorithm_names, enc_alg, enc_key.len * 8); - rthdr->rta_type = XFRMA_ALG_AEAD; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + - enc_key.len); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) + algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AEAD, + sizeof(*algo) + enc_key.len); + if (!algo) { goto failed; } - - algo = (struct xfrm_algo_aead*)RTA_DATA(rthdr); algo->alg_key_len = enc_key.len * 8; algo->alg_icv_len = icv_size; strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; memcpy(algo->alg_key, enc_key.ptr, enc_key.len); - - rthdr = XFRM_RTA_NEXT(rthdr); break; } default: @@ -1283,21 +1296,16 @@ METHOD(kernel_ipsec_t, add_sa, status_t, DBG2(DBG_KNL, " using encryption algorithm %N with key size %d", encryption_algorithm_names, enc_alg, enc_key.len * 8); - rthdr->rta_type = XFRMA_ALG_CRYPT; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_key.len); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) + algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_CRYPT, + sizeof(*algo) + enc_key.len); + if (!algo) { goto failed; } - - algo = (struct xfrm_algo*)RTA_DATA(rthdr); algo->alg_key_len = enc_key.len * 8; strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; memcpy(algo->alg_key, enc_key.ptr, enc_key.len); - - rthdr = XFRM_RTA_NEXT(rthdr); } } @@ -1335,17 +1343,12 @@ METHOD(kernel_ipsec_t, add_sa, status_t, /* the kernel uses SHA256 with 96 bit truncation by default, * use specified truncation size supported by newer kernels. * also use this for untruncated MD5 and SHA1. */ - rthdr->rta_type = XFRMA_ALG_AUTH_TRUNC; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_auth) + - int_key.len); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) + algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH_TRUNC, + sizeof(*algo) + int_key.len); + if (!algo) { goto failed; } - - algo = (struct xfrm_algo_auth*)RTA_DATA(rthdr); algo->alg_key_len = int_key.len * 8; algo->alg_trunc_len = trunc_len; strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); @@ -1356,27 +1359,23 @@ METHOD(kernel_ipsec_t, add_sa, status_t, { struct xfrm_algo* algo; - rthdr->rta_type = XFRMA_ALG_AUTH; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_key.len); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) + algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_AUTH, + sizeof(*algo) + int_key.len); + if (!algo) { goto failed; } - - algo = (struct xfrm_algo*)RTA_DATA(rthdr); algo->alg_key_len = int_key.len * 8; strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; memcpy(algo->alg_key, int_key.ptr, int_key.len); } - rthdr = XFRM_RTA_NEXT(rthdr); } if (ipcomp != IPCOMP_NONE) { - rthdr->rta_type = XFRMA_ALG_COMP; + struct xfrm_algo* algo; + alg_name = lookup_algorithm(COMPRESSION_ALGORITHM, ipcomp); if (alg_name == NULL) { @@ -1387,35 +1386,26 @@ METHOD(kernel_ipsec_t, add_sa, status_t, DBG2(DBG_KNL, " using compression algorithm %N", ipcomp_transform_names, ipcomp); - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) + algo = netlink_reserve(hdr, sizeof(request), XFRMA_ALG_COMP, + sizeof(*algo)); + if (!algo) { goto failed; } - - struct xfrm_algo* algo = (struct xfrm_algo*)RTA_DATA(rthdr); algo->alg_key_len = 0; strncpy(algo->alg_name, alg_name, sizeof(algo->alg_name)); algo->alg_name[sizeof(algo->alg_name) - 1] = '\0'; - - rthdr = XFRM_RTA_NEXT(rthdr); } if (encap) { struct xfrm_encap_tmpl *tmpl; - rthdr->rta_type = XFRMA_ENCAP; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) + tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl)); + if (!tmpl) { goto failed; } - - tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rthdr); tmpl->encap_type = UDP_ENCAP_ESPINUDP; tmpl->encap_sport = htons(src->get_port(src)); tmpl->encap_dport = htons(dst->get_port(dst)); @@ -1430,44 +1420,24 @@ METHOD(kernel_ipsec_t, add_sa, status_t, * No. The reason the kernel ignores NAT-OA is that it recomputes * (or, rather, just ignores) the checksum. If packets pass the IPsec * checks it marks them "checksum ok" so OA isn't needed. */ - rthdr = XFRM_RTA_NEXT(rthdr); } - if (mark.value) + if (!add_mark(hdr, sizeof(request), mark)) { - struct xfrm_mark *mrk; - - rthdr->rta_type = XFRMA_MARK; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) - { - goto failed; - } - - mrk = (struct xfrm_mark*)RTA_DATA(rthdr); - mrk->v = mark.value; - mrk->m = mark.mask; - rthdr = XFRM_RTA_NEXT(rthdr); + goto failed; } if (tfc) { u_int32_t *tfcpad; - rthdr->rta_type = XFRMA_TFCPAD; - rthdr->rta_len = RTA_LENGTH(sizeof(u_int32_t)); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) + tfcpad = netlink_reserve(hdr, sizeof(request), XFRMA_TFCPAD, + sizeof(*tfcpad)); + if (!tfcpad) { goto failed; } - - tfcpad = (u_int32_t*)RTA_DATA(rthdr); *tfcpad = tfc; - rthdr = XFRM_RTA_NEXT(rthdr); } if (protocol != IPPROTO_COMP) @@ -1478,24 +1448,18 @@ METHOD(kernel_ipsec_t, add_sa, status_t, * XFRMA_REPLAY_ESN_VAL attribute to configure a bitmap */ struct xfrm_replay_state_esn *replay; - rthdr->rta_type = XFRMA_REPLAY_ESN_VAL; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) + - (this->replay_window + 7) / 8); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) + replay = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL, + sizeof(*replay) + (this->replay_window + 7) / 8); + if (!replay) { goto failed; } - - replay = (struct xfrm_replay_state_esn*)RTA_DATA(rthdr); /* bmp_len contains number uf __u32's */ replay->bmp_len = this->replay_bmp; replay->replay_window = this->replay_window; DBG2(DBG_KNL, " using replay window of %u packets", this->replay_window); - rthdr = XFRM_RTA_NEXT(rthdr); if (esn) { DBG2(DBG_KNL, " using extended sequence numbers (ESN)"); @@ -1567,22 +1531,9 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this, aevent_id->sa_id.proto = protocol; aevent_id->sa_id.family = dst->get_family(dst); - if (mark.value) + if (!add_mark(hdr, sizeof(request), mark)) { - struct xfrm_mark *mrk; - struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_aevent_id); - - rthdr->rta_type = XFRMA_MARK; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) - { - return; - } - - mrk = (struct xfrm_mark*)RTA_DATA(rthdr); - mrk->v = mark.value; - mrk->m = mark.mask; + return; } if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS) @@ -1668,22 +1619,9 @@ METHOD(kernel_ipsec_t, query_sa, status_t, sa_id->proto = protocol; sa_id->family = dst->get_family(dst); - if (mark.value) + if (!add_mark(hdr, sizeof(request), mark)) { - struct xfrm_mark *mrk; - struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id); - - rthdr->rta_type = XFRMA_MARK; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) - { - return FAILED; - } - - mrk = (struct xfrm_mark*)RTA_DATA(rthdr); - mrk->v = mark.value; - mrk->m = mark.mask; + return FAILED; } if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS) @@ -1771,22 +1709,9 @@ METHOD(kernel_ipsec_t, del_sa, status_t, sa_id->proto = protocol; sa_id->family = dst->get_family(dst); - if (mark.value) + if (!add_mark(hdr, sizeof(request), mark)) { - struct xfrm_mark *mrk; - struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id); - - rthdr->rta_type = XFRMA_MARK; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) - { - return FAILED; - } - - mrk = (struct xfrm_mark*)RTA_DATA(rthdr); - mrk->v = mark.value; - mrk->m = mark.mask; + return FAILED; } switch (this->socket_xfrm->send_ack(this->socket_xfrm, hdr)) @@ -1818,7 +1743,6 @@ METHOD(kernel_ipsec_t, update_sa, status_t, bool old_encap, bool new_encap, mark_t mark) { netlink_buf_t request; - u_char *pos; struct nlmsghdr *hdr, *out = NULL; struct xfrm_usersa_id *sa_id; struct xfrm_usersa_info *out_sa = NULL, *sa; @@ -1853,22 +1777,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t, sa_id->proto = protocol; sa_id->family = dst->get_family(dst); - if (mark.value) + if (!add_mark(hdr, sizeof(request), mark)) { - struct xfrm_mark *mrk; - struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_usersa_id); - - rthdr->rta_type = XFRMA_MARK; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) - { - return FAILED; - } - - mrk = (struct xfrm_mark*)RTA_DATA(rthdr); - mrk->v = mark.value; - mrk->m = mark.mask; + return FAILED; } if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS) @@ -1919,11 +1830,11 @@ METHOD(kernel_ipsec_t, update_sa, status_t, ntohl(spi), src, dst, new_src, new_dst); /* copy over the SA from out to request */ hdr = (struct nlmsghdr*)request; - memcpy(hdr, out, min(out->nlmsg_len, sizeof(request))); hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; hdr->nlmsg_type = XFRM_MSG_NEWSA; hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_info)); sa = NLMSG_DATA(hdr); + memcpy(sa, NLMSG_DATA(out), sizeof(struct xfrm_usersa_info)); sa->family = new_dst->get_family(new_dst); if (!src->ip_equals(src, new_src)) @@ -1937,75 +1848,60 @@ METHOD(kernel_ipsec_t, update_sa, status_t, rta = XFRM_RTA(out, struct xfrm_usersa_info); rtasize = XFRM_PAYLOAD(out, struct xfrm_usersa_info); - pos = (u_char*)XFRM_RTA(hdr, struct xfrm_usersa_info); - while(RTA_OK(rta, rtasize)) + while (RTA_OK(rta, rtasize)) { /* copy all attributes, but not XFRMA_ENCAP if we are disabling it */ if (rta->rta_type != XFRMA_ENCAP || new_encap) { if (rta->rta_type == XFRMA_ENCAP) { /* update encap tmpl */ - tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rta); + tmpl = RTA_DATA(rta); tmpl->encap_sport = ntohs(new_src->get_port(new_src)); tmpl->encap_dport = ntohs(new_dst->get_port(new_dst)); } - memcpy(pos, rta, rta->rta_len); - pos += RTA_ALIGN(rta->rta_len); - hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); + netlink_add_attribute(hdr, rta->rta_type, + chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)), + sizeof(request)); } rta = RTA_NEXT(rta, rtasize); } - rta = (struct rtattr*)pos; if (tmpl == NULL && new_encap) { /* add tmpl if we are enabling it */ - rta->rta_type = XFRMA_ENCAP; - rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); - - hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); - if (hdr->nlmsg_len > sizeof(request)) + tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_ENCAP, sizeof(*tmpl)); + if (!tmpl) { goto failed; } - - tmpl = (struct xfrm_encap_tmpl*)RTA_DATA(rta); tmpl->encap_type = UDP_ENCAP_ESPINUDP; tmpl->encap_sport = ntohs(new_src->get_port(new_src)); tmpl->encap_dport = ntohs(new_dst->get_port(new_dst)); memset(&tmpl->encap_oa, 0, sizeof (xfrm_address_t)); - - rta = XFRM_RTA_NEXT(rta); } if (replay_esn) { - rta->rta_type = XFRMA_REPLAY_ESN_VAL; - rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) + - this->replay_bmp); + struct xfrm_replay_state_esn *state; - hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); - if (hdr->nlmsg_len > sizeof(request)) + state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_ESN_VAL, + sizeof(*state) + this->replay_bmp); + if (!state) { goto failed; } - memcpy(RTA_DATA(rta), replay_esn, - sizeof(struct xfrm_replay_state_esn) + this->replay_bmp); - - rta = XFRM_RTA_NEXT(rta); + memcpy(state, replay_esn, sizeof(*state) + this->replay_bmp); } else if (replay) { - rta->rta_type = XFRMA_REPLAY_VAL; - rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state)); + struct xfrm_replay_state *state; - hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); - if (hdr->nlmsg_len > sizeof(request)) + state = netlink_reserve(hdr, sizeof(request), XFRMA_REPLAY_VAL, + sizeof(*state)); + if (!state) { goto failed; } - memcpy(RTA_DATA(rta), replay, sizeof(struct xfrm_replay_state)); - - rta = XFRM_RTA_NEXT(rta); + memcpy(state, replay, sizeof(*state)); } else { @@ -2102,11 +1998,9 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this, policy_info->lft.soft_use_expires_seconds = 0; policy_info->lft.hard_use_expires_seconds = 0; - struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_info); - if (mapping->type == POLICY_IPSEC) { - struct xfrm_user_tmpl *tmpl = (struct xfrm_user_tmpl*)RTA_DATA(rthdr); + struct xfrm_user_tmpl *tmpl; struct { u_int8_t proto; bool use; @@ -2116,25 +2010,29 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this, { IPPROTO_AH, ipsec->cfg.ah.use }, }; ipsec_mode_t proto_mode = ipsec->cfg.mode; - - rthdr->rta_type = XFRMA_TMPL; - rthdr->rta_len = 0; /* actual length is set below */ + int count = 0; for (i = 0; i < countof(protos); i++) { - if (!protos[i].use) + if (protos[i].use) { - continue; + count++; } + } + tmpl = netlink_reserve(hdr, sizeof(request), XFRMA_TMPL, + count * sizeof(*tmpl)); + if (!tmpl) + { + this->mutex->unlock(this->mutex); + return FAILED; + } - rthdr->rta_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl)); - hdr->nlmsg_len += RTA_ALIGN(RTA_LENGTH(sizeof(struct xfrm_user_tmpl))); - if (hdr->nlmsg_len > sizeof(request)) + for (i = 0; i < countof(protos); i++) + { + if (!protos[i].use) { - this->mutex->unlock(this->mutex); - return FAILED; + continue; } - tmpl->reqid = ipsec->cfg.reqid; tmpl->id.proto = protos[i].proto; tmpl->aalgos = tmpl->ealgos = tmpl->calgos = ~0; @@ -2154,27 +2052,12 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this, /* use transport mode for other SAs */ proto_mode = MODE_TRANSPORT; } - - rthdr = XFRM_RTA_NEXT(rthdr); } - if (ipsec->mark.value) + if (!add_mark(hdr, sizeof(request), ipsec->mark)) { - struct xfrm_mark *mrk; - - rthdr->rta_type = XFRMA_MARK; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) - { - this->mutex->unlock(this->mutex); - return FAILED; - } - - mrk = (struct xfrm_mark*)RTA_DATA(rthdr); - mrk->v = ipsec->mark.value; - mrk->m = ipsec->mark.mask; + this->mutex->unlock(this->mutex); + return FAILED; } this->mutex->unlock(this->mutex); @@ -2196,14 +2079,15 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this, /* install a route, if: * - this is a forward policy (to just get one for each child) - * - we are in tunnel/BEET mode + * - we are in tunnel/BEET mode or install a bypass policy * - routing is not disabled via strongswan.conf */ - if (policy->direction == POLICY_FWD && - ipsec->cfg.mode != MODE_TRANSPORT && this->install_routes) + if (policy->direction == POLICY_FWD && this->install_routes && + (mapping->type != POLICY_IPSEC || ipsec->cfg.mode != MODE_TRANSPORT)) { policy_sa_fwd_t *fwd = (policy_sa_fwd_t*)mapping; route_entry_t *route; + host_t *iface; INIT(route, .prefixlen = policy->sel.prefixlen_s, @@ -2219,9 +2103,17 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this, route->dst_net = chunk_alloc(policy->sel.family == AF_INET ? 4 : 16); memcpy(route->dst_net.ptr, &policy->sel.saddr, route->dst_net.len); + /* get the interface to install the route for. If we have a local + * address, use it. Otherwise (for shunt policies) use the + * routes source address. */ + iface = ipsec->dst; + if (iface->is_anyaddr(iface)) + { + iface = route->src_ip; + } /* install route via outgoing interface */ if (!hydra->kernel_interface->get_interface(hydra->kernel_interface, - ipsec->dst, &route->if_name)) + iface, &route->if_name)) { this->mutex->unlock(this->mutex); route_entry_destroy(route); @@ -2392,23 +2284,9 @@ METHOD(kernel_ipsec_t, query_policy, status_t, policy_id->sel = ts2selector(src_ts, dst_ts); policy_id->dir = direction; - if (mark.value) + if (!add_mark(hdr, sizeof(request), mark)) { - struct xfrm_mark *mrk; - struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_id); - - rthdr->rta_type = XFRMA_MARK; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) - { - return FAILED; - } - - mrk = (struct xfrm_mark*)RTA_DATA(rthdr); - mrk->v = mark.value; - mrk->m = mark.mask; + return FAILED; } if (this->socket_xfrm->send(this->socket_xfrm, hdr, &out, &len) == SUCCESS) @@ -2564,23 +2442,9 @@ METHOD(kernel_ipsec_t, del_policy, status_t, policy_id->sel = current->sel; policy_id->dir = direction; - if (mark.value) + if (!add_mark(hdr, sizeof(request), mark)) { - struct xfrm_mark *mrk; - struct rtattr *rthdr = XFRM_RTA(hdr, struct xfrm_userpolicy_id); - - rthdr->rta_type = XFRMA_MARK; - rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); - if (hdr->nlmsg_len > sizeof(request)) - { - this->mutex->unlock(this->mutex); - return FAILED; - } - - mrk = (struct xfrm_mark*)RTA_DATA(rthdr); - mrk->v = mark.value; - mrk->m = mark.mask; + return FAILED; } if (current->route) @@ -2734,6 +2598,7 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create() INIT(this, .public = { .interface = { + .get_features = _get_features, .get_spi = _get_spi, .get_cpi = _get_cpi, .add_sa = _add_sa, @@ -2822,4 +2687,3 @@ kernel_netlink_ipsec_t *kernel_netlink_ipsec_create() return &this->public; } - diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c index e47887859..3e0725a35 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c @@ -1757,6 +1757,10 @@ METHOD(kernel_net_t, add_ip, status_t, DBG2(DBG_KNL, "virtual IP %H installed on %s", virtual_ip, entry->iface->ifname); this->lock->unlock(this->lock); + /* during IKEv1 reauthentication, children get moved from + * old the new SA before the virtual IP is available. This + * kills the route for our virtual IP, reinstall. */ + queue_route_reinstall(this, strdup(entry->iface->ifname)); return SUCCESS; } } diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c index 561e8529d..fd00c23af 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c @@ -292,7 +292,7 @@ void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data, { struct rtattr *rta; - if (NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(data.len) > buflen) + if (NLMSG_ALIGN(hdr->nlmsg_len) + RTA_LENGTH(data.len) > buflen) { DBG1(DBG_KNL, "unable to add attribute, buffer too small"); return; @@ -304,3 +304,24 @@ void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data, memcpy(RTA_DATA(rta), data.ptr, data.len); hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + rta->rta_len; } + +/** + * Described in header. + */ +void* netlink_reserve(struct nlmsghdr *hdr, int buflen, int type, int len) +{ + struct rtattr *rta; + + if (NLMSG_ALIGN(hdr->nlmsg_len) + RTA_LENGTH(len) > buflen) + { + DBG1(DBG_KNL, "unable to add attribute, buffer too small"); + return NULL; + } + + rta = ((void*)hdr) + NLMSG_ALIGN(hdr->nlmsg_len); + rta->rta_type = type; + rta->rta_len = RTA_LENGTH(len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + rta->rta_len; + + return RTA_DATA(rta); +} diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h index dfd27a21a..8be935bc3 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.h @@ -42,7 +42,8 @@ struct netlink_socket_t { * @param out received netlink message * @param out_len length of the received message */ - status_t (*send)(netlink_socket_t *this, struct nlmsghdr *in, struct nlmsghdr **out, size_t *out_len); + status_t (*send)(netlink_socket_t *this, struct nlmsghdr *in, + struct nlmsghdr **out, size_t *out_len); /** * Send a netlink message and wait for its acknowledge. @@ -67,11 +68,23 @@ netlink_socket_t *netlink_socket_create(int protocol); /** * Creates an rtattr and adds it to the given netlink message. * - * @param hdr netlink message - * @param rta_type type of the rtattr - * @param data data to add to the rtattr - * @param buflen length of the netlink message buffer + * @param hdr netlink message + * @param rta_type type of the rtattr + * @param data data to add to the rtattr + * @param buflen length of the netlink message buffer */ -void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data, size_t buflen); +void netlink_add_attribute(struct nlmsghdr *hdr, int rta_type, chunk_t data, + size_t buflen); + +/** + * Reserve space in a netlink message for given size and type, returning buffer. + * + * @param hdr netlink message + * @param buflen size of full netlink buffer + * @param type RTA type + * @param len length of RTA data + * @return buffer to len bytes of attribute data, NULL on error + */ +void* netlink_reserve(struct nlmsghdr *hdr, int buflen, int type, int len); #endif /* KERNEL_NETLINK_SHARED_H_ */ diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c index 71bdbbe2b..88b028447 100644 --- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c +++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c @@ -953,7 +953,8 @@ static traffic_selector_t* sadb_address2ts(struct sadb_address *address) ts = traffic_selector_create_from_subnet(host, address->sadb_address_prefixlen, address->sadb_address_proto, - host->get_port(host)); + host->get_port(host), + host->get_port(host) ?: 65535); return ts; } @@ -2654,4 +2655,3 @@ kernel_pfkey_ipsec_t *kernel_pfkey_ipsec_create() return &this->public; } - diff --git a/src/libimcv/ietf/ietf_attr.h b/src/libimcv/ietf/ietf_attr.h index a1ba42565..d22175d94 100644 --- a/src/libimcv/ietf/ietf_attr.h +++ b/src/libimcv/ietf/ietf_attr.h @@ -14,8 +14,8 @@ */ /** - * @defgroup ietf_attrt ietf_attr - * @{ @ingroup ietf_attr + * @defgroup ietf_attr ietf_attr + * @{ @ingroup libimcv */ #ifndef IETF_ATTR_H_ diff --git a/src/libimcv/ietf/ietf_attr_assess_result.c b/src/libimcv/ietf/ietf_attr_assess_result.c index 1c0d6b0eb..55226e3bb 100644 --- a/src/libimcv/ietf/ietf_attr_assess_result.c +++ b/src/libimcv/ietf/ietf_attr_assess_result.c @@ -106,7 +106,7 @@ METHOD(pa_tnc_attr_t, build, void, writer = bio_writer_create(ASSESS_RESULT_SIZE); writer->write_uint32(writer, this->result); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libimcv/ietf/ietf_attr_assess_result.h b/src/libimcv/ietf/ietf_attr_assess_result.h index fab8bc3f0..e94b57b88 100644 --- a/src/libimcv/ietf/ietf_attr_assess_result.h +++ b/src/libimcv/ietf/ietf_attr_assess_result.h @@ -15,7 +15,7 @@ /** * @defgroup ietf_attr_assess_resultt ietf_attr_assess_result - * @{ @ingroup ietf + * @{ @ingroup ietf_attr */ #ifndef IETF_ATTR_ASSESS_RESULT_H_ diff --git a/src/libimcv/ietf/ietf_attr_attr_request.c b/src/libimcv/ietf/ietf_attr_attr_request.c index c93c9276e..5dc487030 100644 --- a/src/libimcv/ietf/ietf_attr_attr_request.c +++ b/src/libimcv/ietf/ietf_attr_attr_request.c @@ -125,7 +125,7 @@ METHOD(pa_tnc_attr_t, build, void, } enumerator->destroy(enumerator); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libimcv/ietf/ietf_attr_attr_request.h b/src/libimcv/ietf/ietf_attr_attr_request.h index 387ba345d..fc9e08676 100644 --- a/src/libimcv/ietf/ietf_attr_attr_request.h +++ b/src/libimcv/ietf/ietf_attr_attr_request.h @@ -15,7 +15,7 @@ /** * @defgroup ietf_attr_attr_requestt ietf_attr_attr_request - * @{ @ingroup ietf + * @{ @ingroup ietf_attr */ #ifndef IETF_ATTR_ATTR_REQUEST_H_ diff --git a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c index 2022f45cf..2c6b3d542 100644 --- a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c +++ b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c @@ -106,7 +106,7 @@ METHOD(pa_tnc_attr_t, build, void, writer = bio_writer_create(DEFAULT_PWD_ENABLED_SIZE); writer->write_uint32(writer, this->status); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h index f6026b0e8..6fe1a02b1 100644 --- a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h +++ b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h @@ -15,7 +15,7 @@ /** * @defgroup ietf_attr_default_pwd_enabled ietf_attr_default_pwd_enabled - * @{ @ingroup ietf + * @{ @ingroup ietf_attr */ #ifndef IETF_ATTR_PWD_ENABLED_H_ diff --git a/src/libimcv/ietf/ietf_attr_fwd_enabled.c b/src/libimcv/ietf/ietf_attr_fwd_enabled.c index 911ee5b89..a906b2258 100644 --- a/src/libimcv/ietf/ietf_attr_fwd_enabled.c +++ b/src/libimcv/ietf/ietf_attr_fwd_enabled.c @@ -106,7 +106,7 @@ METHOD(pa_tnc_attr_t, build, void, writer = bio_writer_create(FORWARDING_ENABLED_SIZE); writer->write_uint32(writer, this->fwd_status); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libimcv/ietf/ietf_attr_fwd_enabled.h b/src/libimcv/ietf/ietf_attr_fwd_enabled.h index bfde1a7b1..41714380e 100644 --- a/src/libimcv/ietf/ietf_attr_fwd_enabled.h +++ b/src/libimcv/ietf/ietf_attr_fwd_enabled.h @@ -15,7 +15,7 @@ /** * @defgroup ietf_attr_fwd_enabled ietf_attr_fwd_enabled - * @{ @ingroup ietf + * @{ @ingroup ietf_attr */ #ifndef IETF_ATTR_FWD_ENABLED_H_ diff --git a/src/libimcv/ietf/ietf_attr_installed_packages.c b/src/libimcv/ietf/ietf_attr_installed_packages.c index 72a3c1344..462805e38 100644 --- a/src/libimcv/ietf/ietf_attr_installed_packages.c +++ b/src/libimcv/ietf/ietf_attr_installed_packages.c @@ -144,7 +144,7 @@ METHOD(pa_tnc_attr_t, build, void, } enumerator->destroy(enumerator); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libimcv/ietf/ietf_attr_installed_packages.h b/src/libimcv/ietf/ietf_attr_installed_packages.h index a9f6768e0..b79c4040c 100644 --- a/src/libimcv/ietf/ietf_attr_installed_packages.h +++ b/src/libimcv/ietf/ietf_attr_installed_packages.h @@ -15,7 +15,7 @@ /** * @defgroup ietf_attr_installed_packagest ietf_attr_installed_packages - * @{ @ingroup ietf_attr_installed_packages + * @{ @ingroup ietf_attr */ #ifndef IETF_ATTR_INSTALLED_PACKAGES_H_ diff --git a/src/libimcv/ietf/ietf_attr_numeric_version.c b/src/libimcv/ietf/ietf_attr_numeric_version.c index 797205473..739256457 100644 --- a/src/libimcv/ietf/ietf_attr_numeric_version.c +++ b/src/libimcv/ietf/ietf_attr_numeric_version.c @@ -137,7 +137,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_uint16(writer, this->service_pack_major); writer->write_uint16(writer, this->service_pack_minor); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libimcv/ietf/ietf_attr_numeric_version.h b/src/libimcv/ietf/ietf_attr_numeric_version.h index f7d6c909d..bbda6b895 100644 --- a/src/libimcv/ietf/ietf_attr_numeric_version.h +++ b/src/libimcv/ietf/ietf_attr_numeric_version.h @@ -15,7 +15,7 @@ /** * @defgroup ietf_attr_numeric_versiont ietf_attr_numeric_version - * @{ @ingroup ietf + * @{ @ingroup ietf_attr */ #ifndef IETF_ATTR_NUMERIC_VERSION_H_ diff --git a/src/libimcv/ietf/ietf_attr_op_status.c b/src/libimcv/ietf/ietf_attr_op_status.c index d9610b29d..23530684a 100644 --- a/src/libimcv/ietf/ietf_attr_op_status.c +++ b/src/libimcv/ietf/ietf_attr_op_status.c @@ -153,7 +153,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_uint16(writer, 0x0000); writer->write_data (writer, chunk_create(last_use, 20)); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libimcv/ietf/ietf_attr_op_status.h b/src/libimcv/ietf/ietf_attr_op_status.h index 2e14148c4..b70fab608 100644 --- a/src/libimcv/ietf/ietf_attr_op_status.h +++ b/src/libimcv/ietf/ietf_attr_op_status.h @@ -15,7 +15,7 @@ /** * @defgroup ietf_attr_op_statust ietf_attr_op_status - * @{ @ingroup ietf + * @{ @ingroup ietf_attr */ #ifndef IETF_ATTR_OP_STATUS_H_ @@ -40,7 +40,7 @@ enum op_status_t { }; extern enum_name_t *op_status_names; - + /** * Operational Result type */ @@ -92,7 +92,7 @@ struct ietf_attr_op_status_t { * * @param status Operational Status * @param result Operational Result - * @param last_use Time of last use + * @param last_use Time of last use */ pa_tnc_attr_t* ietf_attr_op_status_create(u_int8_t status, u_int8_t result, time_t last_use); diff --git a/src/libimcv/ietf/ietf_attr_pa_tnc_error.c b/src/libimcv/ietf/ietf_attr_pa_tnc_error.c index f92022fe0..5f20f8958 100644 --- a/src/libimcv/ietf/ietf_attr_pa_tnc_error.c +++ b/src/libimcv/ietf/ietf_attr_pa_tnc_error.c @@ -206,7 +206,7 @@ METHOD(pa_tnc_attr_t, build, void, break; } } - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } @@ -325,22 +325,12 @@ METHOD(ietf_attr_pa_tnc_error_t, get_offset, u_int32_t, } /** - * Described in header. + * Generic constructor */ -pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_type_t error_code, - chunk_t msg_info) +static private_ietf_attr_pa_tnc_error_t* create_generic() { private_ietf_attr_pa_tnc_error_t *this; - if (error_code.vendor_id == PEN_IETF) - { - msg_info.len = PA_ERROR_MSG_INFO_SIZE; - } - else if (msg_info.len > PA_ERROR_MSG_INFO_MAX_SIZE) - { - msg_info.len = PA_ERROR_MSG_INFO_MAX_SIZE; - } - INIT(this, .public = { .pa_tnc_attribute = { @@ -360,11 +350,33 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_type_t error_code, .get_offset = _get_offset, }, .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR }, - .error_code = error_code, - .msg_info = chunk_clone(msg_info), .ref = 1, ); + return this; +} + +/** + * Described in header. + */ +pa_tnc_attr_t *ietf_attr_pa_tnc_error_create(pen_type_t error_code, + chunk_t msg_info) +{ + private_ietf_attr_pa_tnc_error_t *this; + + if (error_code.vendor_id == PEN_IETF) + { + msg_info.len = PA_ERROR_MSG_INFO_SIZE; + } + else if (msg_info.len > PA_ERROR_MSG_INFO_MAX_SIZE) + { + msg_info.len = PA_ERROR_MSG_INFO_MAX_SIZE; + } + + this = create_generic(); + this->error_code = error_code; + this->msg_info = chunk_clone(msg_info); + return &this->public.pa_tnc_attribute; } @@ -380,30 +392,10 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_with_offset(pen_type_t error_code, /* the first 8 bytes of the erroneous PA-TNC message are sent back */ msg_info.len = PA_ERROR_MSG_INFO_SIZE; - 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, - .get_ref = _get_ref, - .destroy = _destroy, - }, - .get_error_code = _get_error_code, - .get_msg_info = _get_msg_info, - .get_attr_info = _get_attr_info, - .set_attr_info = _set_attr_info, - .get_offset = _get_offset, - }, - .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR }, - .error_code = error_code, - .msg_info = chunk_clone(msg_info), - .error_offset = error_offset, - .ref = 1, - ); + this = create_generic(); + this->error_code = error_code; + this->msg_info = chunk_clone(msg_info); + this->error_offset = error_offset; return &this->public.pa_tnc_attribute; } @@ -415,30 +407,8 @@ pa_tnc_attr_t *ietf_attr_pa_tnc_error_create_from_data(chunk_t data) { private_ietf_attr_pa_tnc_error_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, - .get_ref = _get_ref, - .destroy = _destroy, - }, - .get_error_code = _get_error_code, - .get_msg_info = _get_msg_info, - .get_attr_info = _get_attr_info, - .set_attr_info = _set_attr_info, - .get_offset = _get_offset, - }, - .type = { PEN_IETF, IETF_ATTR_PA_TNC_ERROR }, - .value = chunk_clone(data), - .ref = 1, - ); + this = create_generic(); + this->value = chunk_clone(data); return &this->public.pa_tnc_attribute; } - - diff --git a/src/libimcv/ietf/ietf_attr_pa_tnc_error.h b/src/libimcv/ietf/ietf_attr_pa_tnc_error.h index a5a10d470..faa38f8f9 100644 --- a/src/libimcv/ietf/ietf_attr_pa_tnc_error.h +++ b/src/libimcv/ietf/ietf_attr_pa_tnc_error.h @@ -15,7 +15,7 @@ /** * @defgroup ietf_attr_pa_tnc_errort ietf_attr_pa_tnc_error - * @{ @ingroup ietf_attr_pa_tnc_error + * @{ @ingroup ietf_attr */ #ifndef IETF_ATTR_PA_TNC_ERROR_H_ @@ -96,7 +96,7 @@ struct ietf_attr_pa_tnc_error_t { * * @param error_code Vendor-specific PA-TNC error code * @param header PA-TNC message header (first 8 bytes) - * + * */ pa_tnc_attr_t* ietf_attr_pa_tnc_error_create(pen_type_t error_code, chunk_t header); @@ -107,7 +107,7 @@ pa_tnc_attr_t* ietf_attr_pa_tnc_error_create(pen_type_t error_code, * @param error_code Vendor-specifica PA-TNC error code * @param header PA-TNC message header (first 8 bytes) * @param error_offset PA-TNC error offset in bytes - * + * */ pa_tnc_attr_t* ietf_attr_pa_tnc_error_create_with_offset(pen_type_t error_code, chunk_t header, diff --git a/src/libimcv/ietf/ietf_attr_port_filter.c b/src/libimcv/ietf/ietf_attr_port_filter.c index 8b8da3a41..1d516a51f 100644 --- a/src/libimcv/ietf/ietf_attr_port_filter.c +++ b/src/libimcv/ietf/ietf_attr_port_filter.c @@ -130,7 +130,7 @@ METHOD(pa_tnc_attr_t, build, void, } enumerator->destroy(enumerator); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libimcv/ietf/ietf_attr_port_filter.h b/src/libimcv/ietf/ietf_attr_port_filter.h index ad5553417..93b696e45 100644 --- a/src/libimcv/ietf/ietf_attr_port_filter.h +++ b/src/libimcv/ietf/ietf_attr_port_filter.h @@ -15,7 +15,7 @@ /** * @defgroup ietf_attr_port_filtert ietf_attr_port_filter - * @{ @ingroup ietf_attr_port_filter + * @{ @ingroup ietf_attr */ #ifndef IETF_ATTR_PORT_FILTER_H_ diff --git a/src/libimcv/ietf/ietf_attr_product_info.c b/src/libimcv/ietf/ietf_attr_product_info.c index 115f00130..a107c27d3 100644 --- a/src/libimcv/ietf/ietf_attr_product_info.c +++ b/src/libimcv/ietf/ietf_attr_product_info.c @@ -119,7 +119,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_uint16(writer, this->product_id); writer->write_data (writer, this->product_name); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libimcv/ietf/ietf_attr_product_info.h b/src/libimcv/ietf/ietf_attr_product_info.h index dfaa67d6c..d0b2d2a84 100644 --- a/src/libimcv/ietf/ietf_attr_product_info.h +++ b/src/libimcv/ietf/ietf_attr_product_info.h @@ -15,7 +15,7 @@ /** * @defgroup ietf_attr_product_infot ietf_attr_product_info - * @{ @ingroup ietf + * @{ @ingroup ietf_attr */ #ifndef IETF_ATTR_PRODUCT_INFO_H_ diff --git a/src/libimcv/ietf/ietf_attr_remediation_instr.c b/src/libimcv/ietf/ietf_attr_remediation_instr.c index f3b4e83dd..5d85e5d89 100644 --- a/src/libimcv/ietf/ietf_attr_remediation_instr.c +++ b/src/libimcv/ietf/ietf_attr_remediation_instr.c @@ -154,7 +154,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_uint32(writer, this->parameters_type.type); writer->write_data (writer, this->parameters); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } @@ -194,14 +194,16 @@ METHOD(pa_tnc_attr_t, process, status_t, DBG1(DBG_TNC, "insufficient data for IETF remediation string"); goto end; } + *offset += 4; + pos = memchr(this->string.ptr, '\0', this->string.len); if (pos) { DBG1(DBG_TNC, "nul termination in IETF remediation string"); - *offset += 1 + (pos - this->string.ptr); + *offset += (pos - this->string.ptr); goto end; } - *offset += 4 + this->string.len; + *offset += this->string.len; if (!reader->read_data8(reader, &this->lang_code)) { @@ -246,12 +248,6 @@ METHOD(ietf_attr_remediation_instr_t, get_parameters, chunk_t, return this->parameters; } -METHOD(ietf_attr_remediation_instr_t, get_uri, chunk_t, - private_ietf_attr_remediation_instr_t *this) -{ - return this->parameters; -} - METHOD(ietf_attr_remediation_instr_t, get_string, chunk_t, private_ietf_attr_remediation_instr_t *this, chunk_t *lang_code) { @@ -284,7 +280,7 @@ pa_tnc_attr_t *ietf_attr_remediation_instr_create(pen_type_t parameters_type, }, .get_parameters_type = _get_parameters_type, .get_parameters = _get_parameters, - .get_uri = _get_uri, + .get_uri = _get_parameters, .get_string = _get_string, }, .type = { PEN_IETF, IETF_ATTR_REMEDIATION_INSTRUCTIONS }, @@ -350,7 +346,7 @@ pa_tnc_attr_t *ietf_attr_remediation_instr_create_from_data(chunk_t data) }, .get_parameters_type = _get_parameters_type, .get_parameters = _get_parameters, - .get_uri = _get_uri, + .get_uri = _get_parameters, .get_string = _get_string, }, .type = { PEN_IETF, IETF_ATTR_REMEDIATION_INSTRUCTIONS }, diff --git a/src/libimcv/ietf/ietf_attr_remediation_instr.h b/src/libimcv/ietf/ietf_attr_remediation_instr.h index 473280c33..5c7c8891b 100644 --- a/src/libimcv/ietf/ietf_attr_remediation_instr.h +++ b/src/libimcv/ietf/ietf_attr_remediation_instr.h @@ -15,7 +15,7 @@ /** * @defgroup ietf_attr_remediation_instrt ietf_attr_remediation_instr - * @{ @ingroup ietf + * @{ @ingroup ietf_attr */ #ifndef IETF_ATTR_REMEDIATION_INSTR_H_ diff --git a/src/libimcv/ietf/ietf_attr_string_version.c b/src/libimcv/ietf/ietf_attr_string_version.c index 8f4129eac..68adde612 100644 --- a/src/libimcv/ietf/ietf_attr_string_version.c +++ b/src/libimcv/ietf/ietf_attr_string_version.c @@ -123,7 +123,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_data8(writer, this->build); writer->write_data8(writer, this->config); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libimcv/ietf/ietf_attr_string_version.h b/src/libimcv/ietf/ietf_attr_string_version.h index 5ffbea8e0..9ccc1f0ee 100644 --- a/src/libimcv/ietf/ietf_attr_string_version.h +++ b/src/libimcv/ietf/ietf_attr_string_version.h @@ -15,7 +15,7 @@ /** * @defgroup ietf_attr_string_versiont ietf_attr_string_version - * @{ @ingroup ietf + * @{ @ingroup ietf_attr */ #ifndef IETF_ATTR_STRING_VERSION_H_ diff --git a/src/libimcv/imc/imc_agent.c b/src/libimcv/imc/imc_agent.c index 161623477..f309abe74 100644 --- a/src/libimcv/imc/imc_agent.c +++ b/src/libimcv/imc/imc_agent.c @@ -190,8 +190,6 @@ METHOD(imc_agent_t, bind_functions, TNC_Result, { this->reserve_additional_id = NULL; } - DBG2(DBG_IMC, "IMC %u \"%s\" provided with bind function", - this->id, this->name); if (this->report_message_types_long) { diff --git a/src/libimcv/imc/imc_agent.h b/src/libimcv/imc/imc_agent.h index aef10c0d7..0a1638f47 100644 --- a/src/libimcv/imc/imc_agent.h +++ b/src/libimcv/imc/imc_agent.h @@ -16,7 +16,7 @@ /** * * @defgroup imc_agent_t imc_agent - * @{ @ingroup imc_agent + * @{ @ingroup libimcv_imc */ #ifndef IMC_AGENT_H_ diff --git a/src/libimcv/imc/imc_msg.c b/src/libimcv/imc/imc_msg.c index 050e63f32..1fc3d3be5 100644 --- a/src/libimcv/imc/imc_msg.c +++ b/src/libimcv/imc/imc_msg.c @@ -91,6 +91,12 @@ METHOD(imc_msg_t, get_dst_id, TNC_UInt32, return this->dst_id; } +METHOD(imc_msg_t, get_msg_type, pen_type_t, + private_imc_msg_t *this) +{ + return this->msg_type; +} + METHOD(imc_msg_t, send_, TNC_Result, private_imc_msg_t *this, bool excl) { @@ -380,6 +386,7 @@ imc_msg_t *imc_msg_create(imc_agent_t *agent, imc_state_t *state, .public = { .get_src_id = _get_src_id, .get_dst_id = _get_dst_id, + .get_msg_type = _get_msg_type, .send = _send_, .receive = _receive, .add_attribute = _add_attribute, @@ -454,4 +461,3 @@ imc_msg_t *imc_msg_create_from_long_data(imc_agent_t *agent, imc_state_t *state, return &this->public; } - diff --git a/src/libimcv/imc/imc_msg.h b/src/libimcv/imc/imc_msg.h index 6dd712e84..588225dbe 100644 --- a/src/libimcv/imc/imc_msg.h +++ b/src/libimcv/imc/imc_msg.h @@ -15,7 +15,7 @@ /** * @defgroup imc_msg imc_msg - * @{ @ingroup libimcv + * @{ @ingroup libimcv_imc */ #ifndef IMC_MSG_H_ @@ -48,6 +48,13 @@ struct imc_msg_t { TNC_UInt32 (*get_dst_id)(imc_msg_t *this); /** + * Get the PA-TNC message type. + * + * @return message type + */ + pen_type_t (*get_msg_type)(imc_msg_t *this); + + /** * Sends one or multiple PA-TNC messages * * @param excl set the excl message flag if supported @@ -134,7 +141,6 @@ imc_msg_t* imc_msg_create_from_data(imc_agent_t *agent, imc_state_t *state, * @param connection_id connection ID * @param src_id source IMV ID * @param dst_id destination IMC ID - * @param msg_flags PA-TNC message flags * @param msg_vid PA-TNC message vendor ID * @param msg_subtype PA-TNC subtype * @param msg received PA-TNC message blob diff --git a/src/libimcv/imc/imc_state.h b/src/libimcv/imc/imc_state.h index c34441f0f..7e763fbe1 100644 --- a/src/libimcv/imc/imc_state.h +++ b/src/libimcv/imc/imc_state.h @@ -16,7 +16,7 @@ /** * * @defgroup imc_state_t imc_state - * @{ @ingroup imc_state + * @{ @ingroup libimcv_imc */ #ifndef IMC_STATE_H_ @@ -68,7 +68,7 @@ struct imc_state_t { /** * Set the maximum size of a PA-TNC message for this TNCCS connection * - * @max_msg_len maximum size of a PA-TNC message + * @param max_msg_len maximum size of a PA-TNC message */ void (*set_max_msg_len)(imc_state_t *this, u_int32_t max_msg_len); diff --git a/src/libimcv/imcv.h b/src/libimcv/imcv.h index a1a5a5f43..3a37e3d8c 100644 --- a/src/libimcv/imcv.h +++ b/src/libimcv/imcv.h @@ -15,7 +15,16 @@ /** * @defgroup libimcv libimcv * - * @defgroup iplugins plugins + * @defgroup libimcv_imc imc + * @ingroup libimcv + * + * @defgroup libimcv_imv imv + * @ingroup libimcv + * + * @defgroup pa_tnc pa_tnc + * @ingroup libimcv + * + * @defgroup libimcv_plugins plugins * @ingroup libimcv * * @addtogroup libimcv diff --git a/src/libimcv/imv/imv_agent.c b/src/libimcv/imv/imv_agent.c index 6a33e396c..8b4247e0f 100644 --- a/src/libimcv/imv/imv_agent.c +++ b/src/libimcv/imv/imv_agent.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Andreas Steffen + * Copyright (C) 2011-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -18,8 +18,11 @@ #include "ietf/ietf_attr_assess_result.h" #include <tncif_names.h> +#include <tncif_identity.h> #include <utils/debug.h> +#include <collections/linked_list.h> +#include <bio/bio_reader.h> #include <threading/rwlock.h> typedef struct private_imv_agent_t private_imv_agent_t; @@ -210,8 +213,6 @@ METHOD(imv_agent_t, bind_functions, TNC_Result, { this->reserve_additional_id = NULL; } - DBG2(DBG_IMV, "IMV %u \"%s\" provided with bind function", - this->id, this->name); if (this->report_message_types_long) { @@ -352,12 +353,59 @@ static u_int32_t get_uint_attribute(private_imv_agent_t *this, TNC_ConnectionID return 0; } +/** + * Read a TNC identity attribute + */ +static linked_list_t* get_identity_attribute(private_imv_agent_t *this, + TNC_ConnectionID id, + TNC_AttributeID attribute_id) +{ + TNC_UInt32 len; + char buf[2048]; + u_int32_t count; + tncif_identity_t *tnc_id; + bio_reader_t *reader; + linked_list_t *list; + + list = linked_list_create(); + + if (!this->get_attribute || + this->get_attribute(this->id, id, attribute_id, sizeof(buf), buf, &len) + != TNC_RESULT_SUCCESS || len > sizeof(buf)) + { + return list; + } + + reader = bio_reader_create(chunk_create(buf, len)); + if (!reader->read_uint32(reader, &count)) + { + goto end; + } + while (count--) + { + tnc_id = tncif_identity_create_empty(); + if (!tnc_id->process(tnc_id, reader)) + { + tnc_id->destroy(tnc_id); + goto end; + } + list->insert_last(list, tnc_id); + } + +end: + reader->destroy(reader); + return list; + } + METHOD(imv_agent_t, create_state, TNC_Result, private_imv_agent_t *this, imv_state_t *state) { TNC_ConnectionID conn_id; char *tnccs_p = NULL, *tnccs_v = NULL, *t_p = NULL, *t_v = NULL; bool has_long = FALSE, has_excl = FALSE, has_soh = FALSE; + linked_list_t *ar_identities; + enumerator_t *enumerator; + tncif_identity_t *tnc_id; u_int32_t max_msg_len; conn_id = state->get_connection_id(state); @@ -378,6 +426,7 @@ METHOD(imv_agent_t, create_state, TNC_Result, t_p = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_PROTOCOL); t_v = get_str_attribute(this, conn_id, TNC_ATTRIBUTEID_IFT_VERSION); max_msg_len = get_uint_attribute(this, conn_id, TNC_ATTRIBUTEID_MAX_MESSAGE_SIZE); + ar_identities = get_identity_attribute(this, conn_id, TNC_ATTRIBUTEID_AR_IDENTITIES); state->set_flags(state, has_long, has_excl); state->set_max_msg_len(state, max_msg_len); @@ -389,6 +438,66 @@ METHOD(imv_agent_t, create_state, TNC_Result, DBG2(DBG_IMV, " over %s %s with maximum PA-TNC message size of %u bytes", t_p ? t_p:"?", t_v ? t_v :"?", max_msg_len); + enumerator = ar_identities->create_enumerator(ar_identities); + while (enumerator->enumerate(enumerator, &tnc_id)) + { + pen_type_t id_type, subject_type, auth_type; + int tcg_id_type, tcg_subject_type, tcg_auth_type; + chunk_t id_value; + identification_t *ar_id; + id_type_t ike_type; + + id_type = tnc_id->get_identity_type(tnc_id); + id_value = tnc_id->get_identity_value(tnc_id); + subject_type = tnc_id->get_subject_type(tnc_id); + auth_type = tnc_id->get_auth_type(tnc_id); + + tcg_id_type = (id_type.vendor_id == PEN_TCG) ? + id_type.type : TNC_ID_UNKNOWN; + tcg_subject_type = (subject_type.vendor_id == PEN_TCG) ? + subject_type.type : TNC_SUBJECT_UNKNOWN; + tcg_auth_type = (auth_type.vendor_id == PEN_TCG) ? + auth_type.type : TNC_AUTH_UNKNOWN; + + switch (tcg_id_type) + { + case TNC_ID_IPV4_ADDR: + ike_type = ID_IPV4_ADDR; + break; + case TNC_ID_IPV6_ADDR: + ike_type = ID_IPV6_ADDR; + break; + case TNC_ID_FQDN: + ike_type = ID_FQDN; + break; + case TNC_ID_RFC822_ADDR: + ike_type = ID_RFC822_ADDR; + break; + case TNC_ID_USER_NAME: + ike_type = ID_USER_ID; + break; + case TNC_ID_DER_ASN1_DN: + ike_type = ID_DER_ASN1_DN; + break; + case TNC_ID_DER_ASN1_GN: + ike_type = ID_IPV4_ADDR; + break; + case TNC_ID_UNKNOWN: + default: + ike_type = ID_KEY_ID; + break; + } + + ar_id = identification_create_from_encoding(ike_type, id_value); + DBG2(DBG_IMV, " %N AR identity '%Y' authenticated by %N", + TNC_Subject_names, tcg_subject_type, ar_id, + TNC_Authentication_names, tcg_auth_type); + state->set_ar_id(state, ar_id); + } + enumerator->destroy(enumerator); + + ar_identities->destroy_offset(ar_identities, + offsetof(tncif_identity_t, destroy)); free(tnccs_p); free(tnccs_v); free(t_p); diff --git a/src/libimcv/imv/imv_agent.h b/src/libimcv/imv/imv_agent.h index 5b2cffefe..6f3d2b4b7 100644 --- a/src/libimcv/imv/imv_agent.h +++ b/src/libimcv/imv/imv_agent.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Andreas Steffen + * Copyright (C) 2011-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -16,7 +16,7 @@ /** * * @defgroup imv_agent_t imv_agent - * @{ @ingroup imv_agent + * @{ @ingroup libimcv_imv */ #ifndef IMV_AGENT_H_ diff --git a/src/libimcv/imv/imv_lang_string.h b/src/libimcv/imv/imv_lang_string.h index 90a66db76..56b4572f8 100644 --- a/src/libimcv/imv/imv_lang_string.h +++ b/src/libimcv/imv/imv_lang_string.h @@ -16,7 +16,7 @@ /** * * @defgroup imv_lang_string_t imv_lang_string - * @{ @ingroup imv_lang_string + * @{ @ingroup libimcv_imv */ #ifndef IMV_LANG_STRING_H_ diff --git a/src/libimcv/imv/imv_msg.c b/src/libimcv/imv/imv_msg.c index 4ed19dd13..496d0ee1c 100644 --- a/src/libimcv/imv/imv_msg.c +++ b/src/libimcv/imv/imv_msg.c @@ -102,6 +102,12 @@ METHOD(imv_msg_t, set_msg_type, void, } } +METHOD(imv_msg_t, get_msg_type, pen_type_t, + private_imv_msg_t *this) +{ + return this->msg_type; +} + METHOD(imv_msg_t, add_attribute, void, private_imv_msg_t *this, pa_tnc_attr_t *attr) { @@ -352,6 +358,7 @@ imv_msg_t *imv_msg_create(imv_agent_t *agent, imv_state_t *state, .get_src_id = _get_src_id, .get_dst_id = _get_dst_id, .set_msg_type = _set_msg_type, + .get_msg_type = _get_msg_type, .send = _send_, .send_assessment = _send_assessment, .receive = _receive, diff --git a/src/libimcv/imv/imv_msg.h b/src/libimcv/imv/imv_msg.h index b639712e8..9e56d9fe7 100644 --- a/src/libimcv/imv/imv_msg.h +++ b/src/libimcv/imv/imv_msg.h @@ -14,8 +14,8 @@ */ /** - * @defgroup imv_msg imv_msg - * @{ @ingroup libimcv + * @defgroup imv_msg_t imv_msg + * @{ @ingroup libimcv_imv */ #ifndef IMV_MSG_H_ @@ -55,6 +55,13 @@ struct imv_msg_t { void (*set_msg_type)(imv_msg_t *this, pen_type_t msg_type); /** + * Get the type of a PA-TNC message. + * + * @return message type + */ + pen_type_t (*get_msg_type)(imv_msg_t *this); + + /** * Sends one or multiple PA-TNC messages * * @param excl set the excl message flag if supported @@ -148,7 +155,6 @@ imv_msg_t* imv_msg_create_from_data(imv_agent_t *agent, imv_state_t *state, * @param connection_id connection ID * @param src_id source IMC ID * @param dst_id destination IMV ID - * @param msg_flags PA-TNC message flags * @param msg_vid PA-TNC message vendor ID * @param msg_subtype PA-TNC subtype * @param msg received PA-TNC message blob diff --git a/src/libimcv/imv/imv_reason_string.c b/src/libimcv/imv/imv_reason_string.c index 18eade01b..d1447ec35 100644 --- a/src/libimcv/imv/imv_reason_string.c +++ b/src/libimcv/imv/imv_reason_string.c @@ -51,7 +51,7 @@ METHOD(imv_reason_string_t, add_reason, void, if (this->reasons.len) { /* append any further reasons */ - this->reasons = chunk_cat("cm", this->reasons, chunk_from_chars('\n'), + this->reasons = chunk_cat("mcc", this->reasons, chunk_from_chars('\n'), chunk_create(s_reason, strlen(s_reason))); } else diff --git a/src/libimcv/imv/imv_reason_string.h b/src/libimcv/imv/imv_reason_string.h index 320b2476a..cb4c27f93 100644 --- a/src/libimcv/imv/imv_reason_string.h +++ b/src/libimcv/imv/imv_reason_string.h @@ -16,7 +16,7 @@ /** * * @defgroup imv_reason_string_t imv_reason_string - * @{ @ingroup imv_reason_string + * @{ @ingroup libimcv_imv */ #ifndef IMV_REASON_STRING_H_ diff --git a/src/libimcv/imv/imv_remediation_string.h b/src/libimcv/imv/imv_remediation_string.h index 9249c2aab..605013abb 100644 --- a/src/libimcv/imv/imv_remediation_string.h +++ b/src/libimcv/imv/imv_remediation_string.h @@ -16,7 +16,7 @@ /** * * @defgroup imv_remediation_string_t imv_remediation_string - * @{ @ingroup imv_remediation_string + * @{ @ingroup libimcv_imv */ #ifndef IMV_REMEDIATION_STRING_H_ diff --git a/src/libimcv/imv/imv_state.h b/src/libimcv/imv/imv_state.h index f40402e2b..5a818e662 100644 --- a/src/libimcv/imv/imv_state.h +++ b/src/libimcv/imv/imv_state.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Andreas Steffen + * Copyright (C) 2011-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -16,7 +16,7 @@ /** * * @defgroup imv_state_t imv_state - * @{ @ingroup imv_state + * @{ @ingroup libimcv_imv */ #ifndef IMV_STATE_H_ @@ -66,7 +66,7 @@ struct imv_state_t { /** * Set the maximum size of a PA-TNC message for this TNCCS connection * - * @max_msg_len maximum size of a PA-TNC message + * @param max_msg_len maximum size of a PA-TNC message */ void (*set_max_msg_len)(imv_state_t *this, u_int32_t max_msg_len); @@ -78,6 +78,20 @@ struct imv_state_t { u_int32_t (*get_max_msg_len)(imv_state_t *this); /** + * Set Access Requestor ID + * + * @param ar_id Access Requestor ID (is not going to be cloned) + */ + void (*set_ar_id)(imv_state_t *this, identification_t *ar_id); + + /** + * Get Access Requestor ID + * + * @return Access Requestor ID + */ + identification_t* (*get_ar_id)(imv_state_t *this); + + /** * Change the connection state * * @param new_state new connection state diff --git a/src/libimcv/ita/ita_attr.c b/src/libimcv/ita/ita_attr.c index 09754aed6..590bc9b5a 100644 --- a/src/libimcv/ita/ita_attr.c +++ b/src/libimcv/ita/ita_attr.c @@ -20,13 +20,14 @@ #include "ita/ita_attr_settings.h" #include "ita/ita_attr_angel.h" -ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_STOP_ANGEL, +ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_ECHO, "Command", "Dummy", "Get Settings", "Settings", "Start Angel", - "Stop Angel" + "Stop Angel", + "Echo" ); /** diff --git a/src/libimcv/ita/ita_attr.h b/src/libimcv/ita/ita_attr.h index d7b06146f..446fa032a 100644 --- a/src/libimcv/ita/ita_attr.h +++ b/src/libimcv/ita/ita_attr.h @@ -14,8 +14,8 @@ */ /** - * @defgroup ita_attrt ita_attr - * @{ @ingroup ita_attr + * @defgroup ita_attr ita_attr + * @{ @ingroup libimcv */ #ifndef ITA_ATTR_H_ @@ -36,7 +36,8 @@ enum ita_attr_t { ITA_ATTR_GET_SETTINGS = 3, ITA_ATTR_SETTINGS = 4, ITA_ATTR_START_ANGEL = 5, - ITA_ATTR_STOP_ANGEL = 6 + ITA_ATTR_STOP_ANGEL = 6, + ITA_ATTR_ECHO = 7 }; /** diff --git a/src/libimcv/ita/ita_attr_angel.h b/src/libimcv/ita/ita_attr_angel.h index c392f7927..d42e7119a 100644 --- a/src/libimcv/ita/ita_attr_angel.h +++ b/src/libimcv/ita/ita_attr_angel.h @@ -14,8 +14,8 @@ */ /** - * @defgroup ita_attr_angelt ita_attr_angel - * @{ @ingroup ita_attr_angel + * @defgroup ita_attr_angel ita_attr_angel + * @{ @ingroup ita_attr */ #ifndef ITA_ATTR_ANGEL_H_ diff --git a/src/libimcv/ita/ita_attr_command.h b/src/libimcv/ita/ita_attr_command.h index 372355197..3926c3887 100644 --- a/src/libimcv/ita/ita_attr_command.h +++ b/src/libimcv/ita/ita_attr_command.h @@ -14,8 +14,8 @@ */ /** - * @defgroup ita_attr_commandt ita_attr_command - * @{ @ingroup ita_attr_command + * @defgroup ita_attr_command ita_attr_command + * @{ @ingroup ita_attr */ #ifndef ITA_ATTR_COMMAND_H_ @@ -54,7 +54,7 @@ pa_tnc_attr_t* ita_attr_command_create(char *command); /** * Creates an ita_attr_command_t object from received data * - * @param command ITA command string + * @param value binary value blob */ pa_tnc_attr_t* ita_attr_command_create_from_data(chunk_t value); diff --git a/src/libimcv/ita/ita_attr_dummy.h b/src/libimcv/ita/ita_attr_dummy.h index afd543b52..1f85ece54 100644 --- a/src/libimcv/ita/ita_attr_dummy.h +++ b/src/libimcv/ita/ita_attr_dummy.h @@ -14,8 +14,8 @@ */ /** - * @defgroup ita_attr_dummyt ita_attr_dummy - * @{ @ingroup ita_attr_dummy + * @defgroup ita_attr_dummy ita_attr_dummy + * @{ @ingroup ita_attr */ #ifndef ITA_ATTR_DUMMY_H_ @@ -47,14 +47,14 @@ struct ita_attr_dummy_t { /** * Creates an ita_attr_dummy_t object with a given size * - * @param size size of dummy attribute value + * @param size size of dummy attribute value */ pa_tnc_attr_t* ita_attr_dummy_create(int size); /** * Creates an ita_attr_dummy_t object from received data * - * @param command ITA command string + * @param value binary value blob */ pa_tnc_attr_t* ita_attr_dummy_create_from_data(chunk_t value); diff --git a/src/libimcv/ita/ita_attr_get_settings.c b/src/libimcv/ita/ita_attr_get_settings.c index 8016b761d..0695af314 100644 --- a/src/libimcv/ita/ita_attr_get_settings.c +++ b/src/libimcv/ita/ita_attr_get_settings.c @@ -128,7 +128,7 @@ METHOD(pa_tnc_attr_t, build, void, } enumerator->destroy(enumerator); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libimcv/ita/ita_attr_get_settings.h b/src/libimcv/ita/ita_attr_get_settings.h index cc5c18140..55306ecc8 100644 --- a/src/libimcv/ita/ita_attr_get_settings.h +++ b/src/libimcv/ita/ita_attr_get_settings.h @@ -14,8 +14,8 @@ */ /** - * @defgroup ita_attr_get_settingst ita_attr_get_settings - * @{ @ingroup ita_attr_get_settings + * @defgroup ita_attr_get_settings ita_attr_get_settings + * @{ @ingroup ita_attr */ #ifndef ITA_ATTR_GET_SETTINGS_H_ diff --git a/src/libimcv/ita/ita_attr_settings.c b/src/libimcv/ita/ita_attr_settings.c index 7941cf69e..9ce253d28 100644 --- a/src/libimcv/ita/ita_attr_settings.c +++ b/src/libimcv/ita/ita_attr_settings.c @@ -157,7 +157,7 @@ METHOD(pa_tnc_attr_t, build, void, } enumerator->destroy(enumerator); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libimcv/ita/ita_attr_settings.h b/src/libimcv/ita/ita_attr_settings.h index f3d1fd438..eb7eedae3 100644 --- a/src/libimcv/ita/ita_attr_settings.h +++ b/src/libimcv/ita/ita_attr_settings.h @@ -14,8 +14,8 @@ */ /** - * @defgroup ita_attr_settingst ita_attr_settings - * @{ @ingroup ita_attr_settings + * @defgroup ita_attr_settings ita_attr_settings + * @{ @ingroup ita_attr */ #ifndef ITA_ATTR_SETTINGS_H_ diff --git a/src/libimcv/os_info/os_info.c b/src/libimcv/os_info/os_info.c index 13374c876..2c49cb01d 100644 --- a/src/libimcv/os_info/os_info.c +++ b/src/libimcv/os_info/os_info.c @@ -156,7 +156,7 @@ METHOD(os_info_t, get_uptime, time_t, { const char proc_uptime[] = "/proc/uptime"; FILE *file; - time_t uptime; + u_int uptime; file = fopen(proc_uptime, "r"); if (!file) diff --git a/src/libimcv/pa_tnc/pa_tnc_attr.h b/src/libimcv/pa_tnc/pa_tnc_attr.h index 9abdba78c..e2ce06ee4 100644 --- a/src/libimcv/pa_tnc/pa_tnc_attr.h +++ b/src/libimcv/pa_tnc/pa_tnc_attr.h @@ -15,7 +15,7 @@ /** * @defgroup pa_tnc_attr pa_tnc_attr - * @{ @ingroup libimcv + * @{ @ingroup pa_tnc */ #ifndef PA_TNC_ATTR_H_ diff --git a/src/libimcv/pa_tnc/pa_tnc_attr_manager.h b/src/libimcv/pa_tnc/pa_tnc_attr_manager.h index 40c3ab335..121be7f90 100644 --- a/src/libimcv/pa_tnc/pa_tnc_attr_manager.h +++ b/src/libimcv/pa_tnc/pa_tnc_attr_manager.h @@ -15,7 +15,7 @@ /** * @defgroup pa_tnc_attr_manager pa_tnc_attr_manager - * @{ @ingroup libimcv + * @{ @ingroup pa_tnc */ #ifndef PA_TNC_ATTR_MANAGER_H_ @@ -56,7 +56,7 @@ struct pa_tnc_attr_manager_t { * Return the PA-TNC attribute names for a given vendor ID * * @param vendor_id Private Enterprise Number (PEN) - * @return PA-TNC attribute names if found, NULL else + * @return PA-TNC attribute names if found, NULL else */ enum_name_t* (*get_names)(pa_tnc_attr_manager_t *this, pen_t vendor_id); @@ -66,7 +66,7 @@ struct pa_tnc_attr_manager_t { * @param vendor_id Private Enterprise Number (PEN) * @param type PA-TNC attribute type * @param value PA-TNC attribute value as encoded data - * @return PA-TNC attribute object if supported, NULL else + * @return PA-TNC attribute object if supported, NULL else */ pa_tnc_attr_t* (*create)(pa_tnc_attr_manager_t *this, pen_t vendor_id, u_int32_t type, chunk_t value); diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.c b/src/libimcv/pa_tnc/pa_tnc_msg.c index 63445f3a1..140463b83 100644 --- a/src/libimcv/pa_tnc/pa_tnc_msg.c +++ b/src/libimcv/pa_tnc/pa_tnc_msg.c @@ -194,7 +194,7 @@ METHOD(pa_tnc_msg_t, build, bool, enumerator->destroy(enumerator); free(this->encoding.ptr); - this->encoding = chunk_clone(writer->get_buf(writer)); + this->encoding = writer->extract_buf(writer); writer->destroy(writer); return TRUE; @@ -284,6 +284,18 @@ METHOD(pa_tnc_msg_t, process, status_t, } DBG3(DBG_TNC, "%B", &value); + if (vendor_id == PEN_RESERVED) + { + error = ietf_attr_pa_tnc_error_create_with_offset(error_code, + this->encoding, offset + 1); + goto err; + } + if (type == IETF_ATTR_RESERVED) + { + error = ietf_attr_pa_tnc_error_create_with_offset(error_code, + this->encoding, offset + 4); + goto err; + } attr = imcv_pa_tnc_attributes->create(imcv_pa_tnc_attributes, vendor_id, type, value); if (!attr) diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.h b/src/libimcv/pa_tnc/pa_tnc_msg.h index 332f2506f..218d3d673 100644 --- a/src/libimcv/pa_tnc/pa_tnc_msg.h +++ b/src/libimcv/pa_tnc/pa_tnc_msg.h @@ -15,7 +15,7 @@ /** * @defgroup pa_tnc_msg pa_tnc_msg - * @{ @ingroup libimcv + * @{ @ingroup pa_tnc */ #ifndef PA_TNC_MSG_H_ diff --git a/src/libimcv/plugins/imc_os/imc_os_state.h b/src/libimcv/plugins/imc_os/imc_os_state.h index 1fe23175a..366e2b60c 100644 --- a/src/libimcv/plugins/imc_os/imc_os_state.h +++ b/src/libimcv/plugins/imc_os/imc_os_state.h @@ -14,9 +14,11 @@ */ /** + * @defgroup imc_os imc_os + * @ingroup libimcv_plugins * * @defgroup imc_os_state_t imc_os_state - * @{ @ingroup imc_os_state + * @{ @ingroup imc_os */ #ifndef IMC_OS_STATE_H_ diff --git a/src/libimcv/plugins/imc_scanner/imc_scanner_state.h b/src/libimcv/plugins/imc_scanner/imc_scanner_state.h index 76aa4165b..3b40575e3 100644 --- a/src/libimcv/plugins/imc_scanner/imc_scanner_state.h +++ b/src/libimcv/plugins/imc_scanner/imc_scanner_state.h @@ -13,9 +13,11 @@ */ /** + * @defgroup imc_scanner imc_scanner + * @ingroup libimcv_plugins * * @defgroup imc_scanner_state_t imc_scanner_state - * @{ @ingroup imc_scanner_state + * @{ @ingroup imc_scanner */ #ifndef IMC_SCANNER_STATE_H_ diff --git a/src/libimcv/plugins/imc_test/imc_test_state.h b/src/libimcv/plugins/imc_test/imc_test_state.h index 402fd14b3..5f9ee2537 100644 --- a/src/libimcv/plugins/imc_test/imc_test_state.h +++ b/src/libimcv/plugins/imc_test/imc_test_state.h @@ -13,9 +13,11 @@ */ /** + * @defgroup imc_test imc_test + * @ingroup libimcv_plugins * * @defgroup imc_test_state_t imc_test_state - * @{ @ingroup imc_test_state + * @{ @ingroup imc_test */ #ifndef IMC_TEST_STATE_H_ diff --git a/src/libimcv/plugins/imv_os/imv_os.c b/src/libimcv/plugins/imv_os/imv_os.c index 65538df07..e63fc73b1 100644 --- a/src/libimcv/plugins/imv_os/imv_os.c +++ b/src/libimcv/plugins/imv_os/imv_os.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Andreas Steffen + * Copyright (C) 2012-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -360,7 +360,9 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) out_msg->add_attribute(out_msg, attr); } - if (fatal_error) + if (fatal_error || + (os_state->get_attribute_request(os_state) && + os_state->get_info(os_state, NULL, NULL, NULL) == NULL)) { state->set_recommendation(state, TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION, @@ -371,7 +373,8 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) /* If all Installed Packages attributes were received, go to assessment */ if (!assessment && !os_state->get_package_request(os_state) && - !os_state->get_angel_count(os_state)) + !os_state->get_angel_count(os_state) && + os_state->get_info(os_state, NULL, NULL, NULL)) { int device_id, count, count_update, count_blacklist, count_ok; u_int os_settings; @@ -387,7 +390,7 @@ static TNC_Result receive_message(imv_state_t *state, imv_msg_t *in_msg) device_id = os_state->get_device_id(os_state); if (os_db && device_id) { - os_db->set_device_info(os_db, device_id, + os_db->set_device_info(os_db, device_id, state->get_ar_id(state), os_state->get_info(os_state, NULL, NULL, NULL), count, count_update, count_blacklist, os_settings); } @@ -518,6 +521,8 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, { imv_state_t *state; imv_os_state_t *os_state; + TNC_IMV_Action_Recommendation rec; + TNC_IMV_Evaluation_Result eval; TNC_Result result = TNC_RESULT_SUCCESS; if (!imv_os) @@ -531,6 +536,18 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, } os_state = (imv_os_state_t*)state; + state->get_recommendation(state, &rec, &eval); + + /* + * Don't send an attribute request if an evaluation is available + * or if an attribute request has already been sent + */ + if (eval != TNC_IMV_EVALUATION_RESULT_DONT_KNOW || + os_state->get_attribute_request(os_state)) + { + return TNC_RESULT_SUCCESS; + } + if (os_state->get_info(os_state, NULL, NULL, NULL) == NULL) { imv_msg_t *out_msg; @@ -548,6 +565,7 @@ TNC_Result TNC_IMV_BatchEnding(TNC_IMVID imv_id, attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FORWARDING_ENABLED); attr_cast->add(attr_cast, PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED); out_msg->add_attribute(out_msg, attr); + os_state->set_attribute_request(os_state, TRUE); /* send PA-TNC message with excl flag not set */ result = out_msg->send(out_msg, FALSE); diff --git a/src/libimcv/plugins/imv_os/imv_os_database.c b/src/libimcv/plugins/imv_os/imv_os_database.c index c6db9953f..730099af4 100644 --- a/src/libimcv/plugins/imv_os/imv_os_database.c +++ b/src/libimcv/plugins/imv_os/imv_os_database.c @@ -214,12 +214,14 @@ METHOD(imv_os_database_t, get_device_id, int, } METHOD(imv_os_database_t, set_device_info, void, - private_imv_os_database_t *this, int device_id, char *os_info, - int count, int count_update, int count_blacklist, u_int flags) + private_imv_os_database_t *this, int device_id, identification_t *ar_id, + char *os_info, int count, int count_update, int count_blacklist, + u_int flags) { enumerator_t *e; time_t last_time; - int pid = 0, last_pid = 0, last_count_update = 0, last_count_blacklist = 0; + int pid = 0, last_pid = 0, iid = 0, last_iid; + int last_count_update = 0, last_count_blacklist = 0; u_int last_flags; bool found = FALSE; @@ -233,26 +235,47 @@ METHOD(imv_os_database_t, set_device_info, void, e->destroy(e); } - /* if OS ifo string has not been found - register it */ + /* if OS info string has not been found - register it */ if (!pid) { this->db->execute(this->db, &pid, "INSERT INTO products (name) VALUES (?)", DB_TEXT, os_info); } + /* get primary key of AR identity if it exists */ + e = this->db->query(this->db, + "SELECT id FROM identities WHERE type = ? AND data = ?", + DB_INT, ar_id->get_type(ar_id), + DB_BLOB, ar_id->get_encoding(ar_id), DB_INT); + if (e) + { + e->enumerate(e, &iid); + e->destroy(e); + } + + /* if AR identity has not been found - register it */ + if (!iid) + { + this->db->execute(this->db, &iid, + "INSERT INTO identities (type, data) VALUES (?, ?)", + DB_INT, ar_id->get_type(ar_id), + DB_BLOB, ar_id->get_encoding(ar_id)); + } + /* get latest device info record if it exists */ e = this->db->query(this->db, - "SELECT time, product, count_update, count_blacklist, flags " + "SELECT time, ar_id, product, count_update, count_blacklist, flags " "FROM device_infos WHERE device = ? ORDER BY time DESC", - DB_INT, device_id, DB_UINT, DB_INT, DB_INT, DB_INT, DB_UINT); + DB_INT, device_id, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_UINT); if (e) { - found = e->enumerate(e, &last_time, &last_pid, &last_count_update, - &last_count_blacklist, &last_flags); + found = e->enumerate(e, &last_time, &last_iid, &last_pid, + &last_count_update, &last_count_blacklist, + &last_flags); e->destroy(e); } if (found && !last_count_update && !last_count_blacklist && !last_flags && - pid == last_pid) + iid == last_iid && pid == last_pid) { /* update device info */ this->db->execute(this->db, NULL, @@ -266,9 +289,10 @@ METHOD(imv_os_database_t, set_device_info, void, { /* insert device info */ this->db->execute(this->db, NULL, - "INSERT INTO device_infos (device, time, product, count, " - "count_update, count_blacklist, flags) VALUES (?, ?, ?, ?, ?, ?, ?)", - DB_INT, device_id, DB_UINT, time(NULL), DB_INT, pid, + "INSERT INTO device_infos (device, time, ar_id, product, count, " + "count_update, count_blacklist, flags) " + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + DB_INT, device_id, DB_UINT, time(NULL), DB_INT, iid, DB_INT, pid, DB_INT, count, DB_INT, count_update, DB_INT, count_blacklist, DB_UINT, flags); } diff --git a/src/libimcv/plugins/imv_os/imv_os_database.h b/src/libimcv/plugins/imv_os/imv_os_database.h index 9ce748f9b..790467f33 100644 --- a/src/libimcv/plugins/imv_os/imv_os_database.h +++ b/src/libimcv/plugins/imv_os/imv_os_database.h @@ -14,9 +14,8 @@ */ /** - * * @defgroup imv_os_database_t imv_os_database - * @{ @ingroup imv_os_database + * @{ @ingroup imv_os */ #ifndef IMV_OS_DATABASE_H_ @@ -53,13 +52,15 @@ struct imv_os_database_t { * Set health infos for a given device * * @param device_id Device ID primary key + * @param ar_id Access Requestor ID * @param os_info OS info string * @param count Number of installed packages * @param count_update Number of packages to be updated * @param count_blacklist Number of blacklisted packages * @param flags Various flags, e.g. illegal OS settings */ - void (*set_device_info)(imv_os_database_t *this, int device_id, char *os_info, + void (*set_device_info)(imv_os_database_t *this, int device_id, + identification_t *ar_id, char *os_info, int count, int count_update, int count_blacklist, u_int flags); diff --git a/src/libimcv/plugins/imv_os/imv_os_state.c b/src/libimcv/plugins/imv_os/imv_os_state.c index ca6e050f7..6a71a04aa 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.c +++ b/src/libimcv/plugins/imv_os/imv_os_state.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 Andreas Steffen + * Copyright (C) 2012-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -62,6 +62,11 @@ struct private_imv_os_state_t { u_int32_t max_msg_len; /** + * Access Requestor ID + */ + identification_t *ar_id; + + /** * IMV action recommendation */ TNC_IMV_Action_Recommendation rec; @@ -137,6 +142,11 @@ struct private_imv_os_state_t { int count_ok; /** + * Attribute request sent - mandatory response expected + */ + bool attribute_request; + + /** * OS Installed Package request sent - mandatory response expected */ bool package_request; @@ -314,6 +324,19 @@ METHOD(imv_state_t, get_max_msg_len, u_int32_t, return this->max_msg_len; } +METHOD(imv_state_t, set_ar_id, void, + private_imv_os_state_t *this, identification_t *ar_id) +{ + /* no cloning, caller must not destroy object */ + this->ar_id = ar_id; +} + +METHOD(imv_state_t, get_ar_id, identification_t*, + private_imv_os_state_t *this) +{ + return this->ar_id; +} + METHOD(imv_state_t, change_state, void, private_imv_os_state_t *this, TNC_ConnectionState new_state) { @@ -430,6 +453,7 @@ METHOD(imv_state_t, get_remediation_instructions, bool, METHOD(imv_state_t, destroy, void, private_imv_os_state_t *this) { + DESTROY_IF(this->ar_id); DESTROY_IF(this->reason_string); DESTROY_IF(this->remediation_string); this->update_packages->destroy_function(this->update_packages, free); @@ -506,6 +530,18 @@ METHOD(imv_os_state_t, get_count, void, } } +METHOD(imv_os_state_t, set_attribute_request, void, + private_imv_os_state_t *this, bool set) +{ + this->attribute_request = set; +} + +METHOD(imv_os_state_t, get_attribute_request, bool, + private_imv_os_state_t *this) +{ + return this->attribute_request; +} + METHOD(imv_os_state_t, set_package_request, void, private_imv_os_state_t *this, bool set) { @@ -586,6 +622,8 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id) .set_flags = _set_flags, .set_max_msg_len = _set_max_msg_len, .get_max_msg_len = _get_max_msg_len, + .set_ar_id = _set_ar_id, + .get_ar_id = _get_ar_id, .change_state = _change_state, .get_recommendation = _get_recommendation, .set_recommendation = _set_recommendation, @@ -597,6 +635,8 @@ imv_state_t *imv_os_state_create(TNC_ConnectionID connection_id) .get_info = _get_info, .set_count = _set_count, .get_count = _get_count, + .set_attribute_request = _set_attribute_request, + .get_attribute_request = _get_attribute_request, .set_package_request = _set_package_request, .get_package_request = _get_package_request, .set_device_id = _set_device_id, diff --git a/src/libimcv/plugins/imv_os/imv_os_state.h b/src/libimcv/plugins/imv_os/imv_os_state.h index 05abdbb6c..1c2adeaf9 100644 --- a/src/libimcv/plugins/imv_os/imv_os_state.h +++ b/src/libimcv/plugins/imv_os/imv_os_state.h @@ -14,9 +14,11 @@ */ /** + * @defgroup imv_os imv_os + * @ingroup libimcv_plugins * * @defgroup imv_os_state_t imv_os_state - * @{ @ingroup imv_os_state + * @{ @ingroup imv_os */ #ifndef IMV_OS_STATE_H_ @@ -61,7 +63,7 @@ struct imv_os_state_t { * @param type OS type (enumerated) * @param name OS name (string) * @param version OS version - * @return OS name & version as a concatenated string + * @return OS name & version as a concatenated string */ char* (*get_info)(imv_os_state_t *this, os_type_t *os_type, chunk_t *name, chunk_t *version); @@ -87,6 +89,21 @@ struct imv_os_state_t { */ void (*get_count)(imv_os_state_t *this, int *count, int *count_update, int *count_blacklist, int *count_ok); + + /** + * Set/reset attribute request status + * + * @param set TRUE to set, FALSE to clear + */ + void (*set_attribute_request)(imv_os_state_t *this, bool set); + + /** + * Get attribute request status + * + * @return TRUE if set, FALSE if unset + */ + bool (*get_attribute_request)(imv_os_state_t *this); + /** * Set/reset OS Installed Packages request status * diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c index 108e5ff6f..8821ed504 100644 --- a/src/libimcv/plugins/imv_scanner/imv_scanner_state.c +++ b/src/libimcv/plugins/imv_scanner/imv_scanner_state.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Andreas Steffen + * Copyright (C) 2011-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -59,6 +59,11 @@ struct private_imv_scanner_state_t { u_int32_t max_msg_len; /** + * Access Requestor ID + */ + identification_t *ar_id; + + /** * IMV action recommendation */ TNC_IMV_Action_Recommendation rec; @@ -165,6 +170,19 @@ METHOD(imv_state_t, get_max_msg_len, u_int32_t, return this->max_msg_len; } +METHOD(imv_state_t, set_ar_id, void, + private_imv_scanner_state_t *this, identification_t *ar_id) +{ + /* no cloning, caller must not destroy object */ + this->ar_id = ar_id; +} + +METHOD(imv_state_t, get_ar_id, identification_t*, + private_imv_scanner_state_t *this) +{ + return this->ar_id; +} + METHOD(imv_state_t, change_state, void, private_imv_scanner_state_t *this, TNC_ConnectionState new_state) { @@ -238,6 +256,7 @@ METHOD(imv_state_t, get_remediation_instructions, bool, METHOD(imv_state_t, destroy, void, private_imv_scanner_state_t *this) { + DESTROY_IF(this->ar_id); DESTROY_IF(this->reason_string); DESTROY_IF(this->remediation_string); this->violating_ports->destroy_function(this->violating_ports, free); @@ -266,6 +285,8 @@ imv_state_t *imv_scanner_state_create(TNC_ConnectionID connection_id) .set_flags = _set_flags, .set_max_msg_len = _set_max_msg_len, .get_max_msg_len = _get_max_msg_len, + .set_ar_id = _set_ar_id, + .get_ar_id = _get_ar_id, .change_state = _change_state, .get_recommendation = _get_recommendation, .set_recommendation = _set_recommendation, diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner_state.h b/src/libimcv/plugins/imv_scanner/imv_scanner_state.h index 9a0930396..a15eb0778 100644 --- a/src/libimcv/plugins/imv_scanner/imv_scanner_state.h +++ b/src/libimcv/plugins/imv_scanner/imv_scanner_state.h @@ -13,9 +13,11 @@ */ /** + * @defgroup imv_scanner imv_scanner + * @ingroup libimcv_plugins * * @defgroup imv_scanner_state_t imv_scanner_state - * @{ @ingroup imv_scanner_state + * @{ @ingroup imv_scanner */ #ifndef IMV_SCANNER_STATE_H_ diff --git a/src/libimcv/plugins/imv_test/imv_test_state.c b/src/libimcv/plugins/imv_test/imv_test_state.c index 9b9344bf6..385a37452 100644 --- a/src/libimcv/plugins/imv_test/imv_test_state.c +++ b/src/libimcv/plugins/imv_test/imv_test_state.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Andreas Steffen + * Copyright (C) 2011-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -59,6 +59,11 @@ struct private_imv_test_state_t { u_int32_t max_msg_len; /** + * Access Requestor ID + */ + identification_t *ar_id; + + /** * IMV action recommendation */ TNC_IMV_Action_Recommendation rec; @@ -143,6 +148,19 @@ METHOD(imv_state_t, get_max_msg_len, u_int32_t, return this->max_msg_len; } +METHOD(imv_state_t, set_ar_id, void, + private_imv_test_state_t *this, identification_t *ar_id) +{ + /* no cloning, caller must not destroy object */ + this->ar_id = ar_id; +} + +METHOD(imv_state_t, get_ar_id, identification_t*, + private_imv_test_state_t *this) +{ + return this->ar_id; +} + METHOD(imv_state_t, change_state, void, private_imv_test_state_t *this, TNC_ConnectionState new_state) { @@ -191,6 +209,7 @@ METHOD(imv_state_t, get_remediation_instructions, bool, METHOD(imv_state_t, destroy, void, private_imv_test_state_t *this) { + DESTROY_IF(this->ar_id); DESTROY_IF(this->reason_string); this->imcs->destroy_function(this->imcs, free); free(this); @@ -277,6 +296,8 @@ imv_state_t *imv_test_state_create(TNC_ConnectionID connection_id) .set_flags = _set_flags, .set_max_msg_len = _set_max_msg_len, .get_max_msg_len = _get_max_msg_len, + .set_ar_id = _set_ar_id, + .get_ar_id = _get_ar_id, .change_state = _change_state, .get_recommendation = _get_recommendation, .set_recommendation = _set_recommendation, diff --git a/src/libimcv/plugins/imv_test/imv_test_state.h b/src/libimcv/plugins/imv_test/imv_test_state.h index af78d1470..2de5b6ffc 100644 --- a/src/libimcv/plugins/imv_test/imv_test_state.h +++ b/src/libimcv/plugins/imv_test/imv_test_state.h @@ -13,9 +13,11 @@ */ /** + * @defgroup imv_test imv_test + * @ingroup libimcv_plugins * * @defgroup imv_test_state_t imv_test_state - * @{ @ingroup imv_test_state + * @{ @ingroup imv_test */ #ifndef IMV_TEST_STATE_H_ diff --git a/src/libipsec/esp_packet.c b/src/libipsec/esp_packet.c index 16cc687ef..43a3c2a97 100644 --- a/src/libipsec/esp_packet.c +++ b/src/libipsec/esp_packet.c @@ -97,6 +97,18 @@ METHOD(packet_t, set_data, void, return this->packet->set_data(this->packet, data); } +METHOD(packet_t, get_dscp, u_int8_t, + private_esp_packet_t *this) +{ + return this->packet->get_dscp(this->packet); +} + +METHOD(packet_t, set_dscp, void, + private_esp_packet_t *this, u_int8_t value) +{ + this->packet->set_dscp(this->packet, value); +} + METHOD(packet_t, skip_bytes, void, private_esp_packet_t *this, size_t bytes) { @@ -411,6 +423,8 @@ static private_esp_packet_t *esp_packet_create_internal(packet_t *packet) .get_destination = _get_destination, .get_data = _get_data, .set_data = _set_data, + .get_dscp = _get_dscp, + .set_dscp = _set_dscp, .skip_bytes = _skip_bytes, .clone = _clone, .destroy = _destroy, diff --git a/src/libpts/libpts.h b/src/libpts/libpts.h index 7b2959728..0846aaea2 100644 --- a/src/libpts/libpts.h +++ b/src/libpts/libpts.h @@ -15,7 +15,7 @@ /** * @defgroup libpts libpts * - * @defgroup iplugins plugins + * @defgroup libpts_plugins plugins * @ingroup libpts * * @addtogroup libpts diff --git a/src/libpts/plugins/imc_attestation/imc_attestation_process.h b/src/libpts/plugins/imc_attestation/imc_attestation_process.h index 5ada104fa..a2f1b4e3c 100644 --- a/src/libpts/plugins/imc_attestation/imc_attestation_process.h +++ b/src/libpts/plugins/imc_attestation/imc_attestation_process.h @@ -14,9 +14,8 @@ */ /** - * * @defgroup imc_attestation_process_t imc_attestation_process - * @{ @ingroup imc_attestation_process + * @{ @ingroup imc_attestation */ #ifndef IMC_ATTESTATION_PROCESS_H_ diff --git a/src/libpts/plugins/imc_attestation/imc_attestation_state.h b/src/libpts/plugins/imc_attestation/imc_attestation_state.h index e4fca71bb..4b93931c3 100644 --- a/src/libpts/plugins/imc_attestation/imc_attestation_state.h +++ b/src/libpts/plugins/imc_attestation/imc_attestation_state.h @@ -14,9 +14,11 @@ */ /** + * @defgroup imc_attestation imc_attestation + * @ingroup libpts_plugins * * @defgroup imc_attestation_state_t imc_attestation_state - * @{ @ingroup imc_attestation_state + * @{ @ingroup imc_attestation */ #ifndef IMC_ATTESTATION_STATE_H_ diff --git a/src/libpts/plugins/imv_attestation/attest_db.c b/src/libpts/plugins/imv_attestation/attest_db.c index 91e9766d0..5885e26a1 100644 --- a/src/libpts/plugins/imv_attestation/attest_db.c +++ b/src/libpts/plugins/imv_attestation/attest_db.c @@ -804,26 +804,29 @@ METHOD(attest_db_t, list_components, void, METHOD(attest_db_t, list_devices, void, private_attest_db_t *this) { - enumerator_t *e; - chunk_t value; + enumerator_t *e, *e_ar; + chunk_t value, ar_data; char *product; time_t timestamp; - int id, last_id = 0, device_count = 0; + int id, last_id = 0, iid = 0, last_iid = 0, device_count = 0; int count, count_update, count_blacklist; + id_type_t ar_type; + identification_t *ar_id = NULL; u_int tstamp, flags = 0; e = this->db->query(this->db, "SELECT d.id, d.value, i.time, i.count, i.count_update, " - "i.count_blacklist, i.flags, p.name FROM devices AS d " + "i.count_blacklist, i.flags, i.ar_id, p.name FROM devices AS d " "JOIN device_infos AS i ON d.id = i.device " "JOIN products AS p ON p.id = i.product " "ORDER BY d.value, i.time DESC", - DB_INT, DB_BLOB, DB_UINT, DB_INT, DB_INT, DB_INT, DB_UINT, DB_TEXT); + DB_INT, DB_BLOB, DB_UINT, DB_INT, DB_INT, DB_INT, DB_UINT, + DB_INT, DB_TEXT); if (e) { while (e->enumerate(e, &id, &value, &tstamp, &count, &count_update, - &count_blacklist, &flags, &product)) + &count_blacklist, &flags, &iid, &product)) { if (id != last_id) { @@ -832,10 +835,35 @@ METHOD(attest_db_t, list_devices, void, last_id = id; } timestamp = tstamp; - printf(" %T, %4d, %3d, %3d, %1u, '%s'\n", ×tamp, this->utc, + printf(" %T, %4d, %3d, %3d, %1u, '%s'", ×tamp, this->utc, count, count_update, count_blacklist, flags, product); + if (iid) + { + if (iid != last_iid) + { + DESTROY_IF(ar_id); + ar_id = NULL; + + e_ar = this->db->query(this->db, + "SELECT type, data FROM identities " + "WHERE id = ?", DB_INT, iid, DB_INT, DB_BLOB); + if (e_ar->enumerate(e_ar, &ar_type, &ar_data)) + { + ar_id = identification_create_from_encoding(ar_type, + ar_data); + } + e_ar->destroy(e_ar); + } + if (ar_id) + { + printf(" %Y", ar_id); + } + } + printf("\n"); } e->destroy(e); + DESTROY_IF(ar_id); + printf("%d device%s found\n", device_count, (device_count == 1) ? "" : "s"); } diff --git a/src/libpts/plugins/imv_attestation/attest_db.h b/src/libpts/plugins/imv_attestation/attest_db.h index e2297d0c4..a20023fcd 100644 --- a/src/libpts/plugins/imv_attestation/attest_db.h +++ b/src/libpts/plugins/imv_attestation/attest_db.h @@ -14,9 +14,8 @@ */ /** - * * @defgroup attest_db_t attest_db - * @{ @ingroup attest_db + * @{ @ingroup libpts */ #ifndef ATTEST_DB_H_ diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_build.h b/src/libpts/plugins/imv_attestation/imv_attestation_build.h index 0fc10f0ce..108f6f923 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_build.h +++ b/src/libpts/plugins/imv_attestation/imv_attestation_build.h @@ -14,9 +14,8 @@ */ /** - * * @defgroup imv_attestation_build_t imv_attestation_build - * @{ @ingroup imv_attestation_build + * @{ @ingroup imv_attestation */ #ifndef IMV_ATTESTATION_BUILD_H_ diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_process.h b/src/libpts/plugins/imv_attestation/imv_attestation_process.h index 73b4251e0..74e4644b4 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_process.h +++ b/src/libpts/plugins/imv_attestation/imv_attestation_process.h @@ -14,9 +14,8 @@ */ /** - * * @defgroup imv_attestation_process_t imv_attestation_process - * @{ @ingroup imv_attestation_process + * @{ @ingroup imv_attestation */ #ifndef IMV_ATTESTATION_PROCESS_H_ diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.c b/src/libpts/plugins/imv_attestation/imv_attestation_state.c index 93da9aee5..9d95ac010 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_state.c +++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.c @@ -1,5 +1,6 @@ /* - * Copyright (C) 2011-2012 Sansar Choinyambuu, Andreas Steffen + * Copyright (C) 2011-2012 Sansar Choinyambuu + * Copyright (C) 2011-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -63,6 +64,11 @@ struct private_imv_attestation_state_t { u_int32_t max_msg_len; /** + * Access Requestor ID + */ + identification_t *ar_id; + + /** * IMV Attestation handshake state */ imv_attestation_handshake_state_t handshake_state; @@ -215,6 +221,19 @@ METHOD(imv_state_t, get_max_msg_len, u_int32_t, return this->max_msg_len; } +METHOD(imv_state_t, set_ar_id, void, + private_imv_attestation_state_t *this, identification_t *ar_id) +{ + /* no cloning, caller must not destroy object */ + this->ar_id = ar_id; +} + +METHOD(imv_state_t, get_ar_id, identification_t*, + private_imv_attestation_state_t *this) +{ + return this->ar_id; +} + METHOD(imv_state_t, change_state, void, private_imv_attestation_state_t *this, TNC_ConnectionState new_state) { @@ -288,6 +307,7 @@ METHOD(imv_state_t, get_remediation_instructions, bool, METHOD(imv_state_t, destroy, void, private_imv_attestation_state_t *this) { + DESTROY_IF(this->ar_id); DESTROY_IF(this->reason_string); this->file_meas_requests->destroy_function(this->file_meas_requests, free); this->components->destroy_function(this->components, (void *)free_func_comp); @@ -479,6 +499,8 @@ imv_state_t *imv_attestation_state_create(TNC_ConnectionID connection_id) .set_flags = _set_flags, .set_max_msg_len = _set_max_msg_len, .get_max_msg_len = _get_max_msg_len, + .set_ar_id = _set_ar_id, + .get_ar_id = _get_ar_id, .change_state = _change_state, .get_recommendation = _get_recommendation, .set_recommendation = _set_recommendation, diff --git a/src/libpts/plugins/imv_attestation/imv_attestation_state.h b/src/libpts/plugins/imv_attestation/imv_attestation_state.h index f64314e71..ab77d3042 100644 --- a/src/libpts/plugins/imv_attestation/imv_attestation_state.h +++ b/src/libpts/plugins/imv_attestation/imv_attestation_state.h @@ -14,9 +14,11 @@ */ /** + * @defgroup imv_attestation imv_attestation + * @ingroup libpts_plugins * * @defgroup imv_attestation_state_t imv_attestation_state - * @{ @ingroup imv_attestation_state + * @{ @ingroup imv_attestation */ #ifndef IMV_ATTESTATION_STATE_H_ @@ -73,7 +75,7 @@ struct imv_attestation_state_t { */ imv_attestation_handshake_state_t (*get_handshake_state)( imv_attestation_state_t *this); - + /** * Set state of the handshake * @@ -133,7 +135,7 @@ struct imv_attestation_state_t { /** * Get a Functional Component with a given name * - * @param name Name of the requested Functional Component + * @param name Name of the requested Functional Component * @return Functional Component if found, NULL otherwise */ pts_component_t* (*get_component)(imv_attestation_state_t *this, diff --git a/src/libpts/plugins/imv_attestation/tables.sql b/src/libpts/plugins/imv_attestation/tables.sql index 8a79ea7cf..0c038d365 100644 --- a/src/libpts/plugins/imv_attestation/tables.sql +++ b/src/libpts/plugins/imv_attestation/tables.sql @@ -126,13 +126,21 @@ CREATE INDEX devices_value ON devices ( DROP TABLE IF EXISTS device_infos; CREATE TABLE device_infos ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, device INTEGER NOT NULL, time INTEGER NOT NULL, + ar_id INTEGER DEFAULT 0, product INTEGER DEFAULT 0, count INTEGER DEFAULT 0, count_update INTEGER DEFAULT 0, count_blacklist INTEGER DEFAULT 0, - flags INTEGER DEFAULT 0, - PRIMARY KEY (device, time) + flags INTEGER DEFAULT 0 ); +DROP TABLE IF EXISTS identities; +CREATE TABLE identities ( + id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + type INTEGER NOT NULL, + data BLOB NOT NULL, + UNIQUE (type, data) +); diff --git a/src/libpts/pts/components/pts_comp_func_name.h b/src/libpts/pts/components/pts_comp_func_name.h index a3ffa1ba9..90ad7083f 100644 --- a/src/libpts/pts/components/pts_comp_func_name.h +++ b/src/libpts/pts/components/pts_comp_func_name.h @@ -95,7 +95,7 @@ struct pts_comp_func_name_t { * * @param vid PTS Component Functional Name Vendor ID * @param name PTS Component Functional Name - * @param PTS Component Functional Name Qualifier + * @param qualifier PTS Component Functional Name Qualifier */ pts_comp_func_name_t* pts_comp_func_name_create(u_int32_t vid, u_int32_t name, u_int8_t qualifier); diff --git a/src/libpts/pts/pts.c b/src/libpts/pts/pts.c index 84a9961c8..f646d67e1 100644 --- a/src/libpts/pts/pts.c +++ b/src/libpts/pts/pts.c @@ -1043,7 +1043,7 @@ METHOD(pts_t, get_quote_info, bool, } /* TPM Quote Info */ - *out_quote_info = chunk_clone(writer->get_buf(writer)); + *out_quote_info = writer->extract_buf(writer); DBG3(DBG_PTS, "constructed TPM Quote Info: %B", out_quote_info); writer->destroy(writer); diff --git a/src/libpts/pts/pts.h b/src/libpts/pts/pts.h index 423a4c802..11154aa38 100644 --- a/src/libpts/pts/pts.h +++ b/src/libpts/pts/pts.h @@ -15,7 +15,7 @@ /** * @defgroup pts pts - * @{ @ingroup pts + * @{ @ingroup libpts */ #ifndef PTS_H_ diff --git a/src/libpts/pts/pts_dh_group.h b/src/libpts/pts/pts_dh_group.h index 8664a4b84..2aab90263 100644 --- a/src/libpts/pts/pts_dh_group.h +++ b/src/libpts/pts/pts_dh_group.h @@ -48,12 +48,12 @@ enum pts_dh_group_t { * Diffie-Hellman Group Values * see section 3.8.6 of PTS Protocol: Binding to TNC IF-M Specification * - * 1 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 + * 1 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |1|2|3|4|5|R|R|R|R|R|R|R|R|R|R|R| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * + * */ /** @@ -90,8 +90,8 @@ bool pts_dh_group_update(char *dh_group, pts_dh_group_t *dh_groups); * @param offered_groups set of offered DH groups * @return selected DH group */ -pts_dh_group_t pts_dh_group_select(pts_dh_group_t supported_dh_groups, - pts_dh_group_t offered_dh_groups); +pts_dh_group_t pts_dh_group_select(pts_dh_group_t supported_groups, + pts_dh_group_t offered_groups); /** * Convert pts_dh_group_t to diffie_hellman_group_t diff --git a/src/libpts/pts/pts_file_meas.h b/src/libpts/pts/pts_file_meas.h index 71efd5026..a13bb29ba 100644 --- a/src/libpts/pts/pts_file_meas.h +++ b/src/libpts/pts/pts_file_meas.h @@ -57,7 +57,7 @@ struct pts_file_meas_t { /** * Create a PTS File Measurement enumerator * - * @return Enumerator returning filename and measurement + * @return Enumerator returning filename and measurement */ enumerator_t* (*create_enumerator)(pts_file_meas_t *this); @@ -76,7 +76,7 @@ struct pts_file_meas_t { * Verify stored hashes against PTS File Measurements * * @param e_hash Hash enumerator - * @paraem is_dir TRUE for directory contents hashes + * @param is_dir TRUE for directory contents hashes * @return TRUE if all hashes match a measurement */ bool (*verify)(pts_file_meas_t *this, enumerator_t *e_hash, bool is_dir); diff --git a/src/libpts/tcg/tcg_attr.c b/src/libpts/tcg/tcg_attr.c index 656791a8f..b91bf8283 100644 --- a/src/libpts/tcg/tcg_attr.c +++ b/src/libpts/tcg/tcg_attr.c @@ -31,8 +31,23 @@ #include "tcg/tcg_pts_attr_req_file_meta.h" #include "tcg/tcg_pts_attr_unix_file_meta.h" -ENUM_BEGIN(tcg_attr_names, TCG_PTS_REQ_FUNC_COMP_EVID, +ENUM_BEGIN(tcg_attr_names, TCG_SCAP_REFERENCES, + TCG_SCAP_SUMMARY_RESULTS, + "SCAP References", + "SCAP Capabilities and Inventory", + "SCAP Content", + "SCAP Assessment", + "SCAP Results", + "SCAP Summary Results"); +ENUM_NEXT(tcg_attr_names, TCG_SWID_INVENTORY_REQUEST, + TCG_SWID_TAG_IDENTIFIER_RESPONSE, + TCG_SCAP_SUMMARY_RESULTS, + "SWID Inventory Request", + "SWID Tag Response", + "SWID Tag Identifier Response"); +ENUM_NEXT(tcg_attr_names, TCG_PTS_REQ_FUNC_COMP_EVID, TCG_PTS_REQ_FUNC_COMP_EVID, + TCG_SWID_TAG_IDENTIFIER_RESPONSE, "Request Functional Component Evidence"); ENUM_NEXT(tcg_attr_names, TCG_PTS_GEN_ATTEST_EVID, TCG_PTS_GEN_ATTEST_EVID, diff --git a/src/libpts/tcg/tcg_attr.h b/src/libpts/tcg/tcg_attr.h index b45e1488f..ed6c97619 100644 --- a/src/libpts/tcg/tcg_attr.h +++ b/src/libpts/tcg/tcg_attr.h @@ -14,8 +14,8 @@ */ /** - * @defgroup tcg_attrt tcg_attr - * @{ @ingroup tcg_attr + * @defgroup tcg_attr tcg_attr + * @{ @ingroup libpts */ #ifndef TCG_ATTR_H_ @@ -31,6 +31,19 @@ typedef enum tcg_attr_t tcg_attr_t; */ enum tcg_attr_t { + /* SCAP Messages */ + TCG_SCAP_REFERENCES = 0x00000001, + TCG_SCAP_CAPS_AND_INVENTORY = 0x00000002, + TCG_SCAP_CONTENT = 0x00000003, + TCG_SCAP_ASSESSMENT = 0x00000004, + TCG_SCAP_RESULTS = 0x00000005, + TCG_SCAP_SUMMARY_RESULTS = 0x00000006, + + /* SWID Messages */ + TCG_SWID_INVENTORY_REQUEST = 0x00000011, + TCG_SWID_TAG_RESPONSE = 0x00000012, + TCG_SWID_TAG_IDENTIFIER_RESPONSE = 0x00000013, + /* PTS Protocol Negotiations */ TCG_PTS_REQ_PROTO_CAPS = 0x01000000, TCG_PTS_PROTO_CAPS = 0x02000000, diff --git a/src/libpts/tcg/tcg_pts_attr_aik.c b/src/libpts/tcg/tcg_pts_attr_aik.c index d5bbdc9cd..17a8db5d6 100644 --- a/src/libpts/tcg/tcg_pts_attr_aik.c +++ b/src/libpts/tcg/tcg_pts_attr_aik.c @@ -123,9 +123,9 @@ METHOD(pa_tnc_attr_t, build, void, writer = bio_writer_create(PTS_AIK_SIZE); writer->write_uint8(writer, flags); writer->write_data (writer, aik_blob); - this->value = chunk_clone(writer->get_buf(writer)); - free(aik_blob.ptr); + this->value = writer->extract_buf(writer); writer->destroy(writer); + free(aik_blob.ptr); } METHOD(pa_tnc_attr_t, process, status_t, diff --git a/src/libpts/tcg/tcg_pts_attr_aik.h b/src/libpts/tcg/tcg_pts_attr_aik.h index 96e90582b..758fd58db 100644 --- a/src/libpts/tcg/tcg_pts_attr_aik.h +++ b/src/libpts/tcg/tcg_pts_attr_aik.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_aik tcg_pts_attr_aik - * @{ @ingroup tcg_pts_attr_aik + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_AIK_H_ @@ -38,7 +38,7 @@ struct tcg_pts_attr_aik_t { * Public PA-TNC attribute interface */ pa_tnc_attr_t pa_tnc_attribute; - + /** * Get AIK * @@ -50,7 +50,7 @@ struct tcg_pts_attr_aik_t { /** * Creates an tcg_pts_attr_aik_t object - * + * * @param aik Attestation Identity Key */ pa_tnc_attr_t* tcg_pts_attr_aik_create(certificate_t *aik); diff --git a/src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.c b/src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.c index 4d7281243..6119b4973 100644 --- a/src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.c +++ b/src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.c @@ -128,7 +128,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_data (writer, this->initiator_value); writer->write_data (writer, this->initiator_nonce); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.h b/src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.h index 7148065c5..57cb5a9b6 100644 --- a/src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.h +++ b/src/libpts/tcg/tcg_pts_attr_dh_nonce_finish.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_dh_nonce_finish tcg_pts_attr_dh_nonce_finish - * @{ @ingroup tcg_pts_attr_dh_nonce_finish + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_DH_NONCE_FINISH_H_ @@ -64,7 +64,7 @@ struct tcg_pts_attr_dh_nonce_finish_t { * @return DH Initiator Nonce */ chunk_t (*get_initiator_nonce)(tcg_pts_attr_dh_nonce_finish_t *this); - + }; /** @@ -76,7 +76,7 @@ struct tcg_pts_attr_dh_nonce_finish_t { */ pa_tnc_attr_t* tcg_pts_attr_dh_nonce_finish_create( pts_meas_algorithms_t hash_algo, - chunk_t initiator_value, + chunk_t initiator_value, chunk_t initiator_nonce); /** diff --git a/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.c b/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.c index 7796dbaab..7761b977d 100644 --- a/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.c +++ b/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.c @@ -117,7 +117,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_uint8 (writer, this->min_nonce_len); writer->write_uint16(writer, this->dh_groups); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.h b/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.h index 170077156..22e1bd189 100644 --- a/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.h +++ b/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_req.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_dh_nonce_params_req tcg_pts_attr_dh_nonce_params_req - * @{ @ingroup tcg_pts_attr_dh_nonce_params_req + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_DH_NONCE_PARAMS_REQ_H_ diff --git a/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.c b/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.c index 1e82e7098..eb0d0e533 100644 --- a/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.c +++ b/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.c @@ -136,7 +136,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_data (writer, this->responder_nonce); writer->write_data (writer, this->responder_value); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.h b/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.h index d2141f8b9..aaf85ef37 100644 --- a/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.h +++ b/src/libpts/tcg/tcg_pts_attr_dh_nonce_params_resp.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_dh_nonce_params_resp tcg_pts_attr_dh_nonce_params_resp - * @{ @ingroup tcg_pts_attr_dh_nonce_params_resp + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_DH_NONCE_PARAMS_RESP_H_ @@ -67,7 +67,7 @@ struct tcg_pts_attr_dh_nonce_params_resp_t { * @return DH Responder Public Value */ chunk_t (*get_responder_value)(tcg_pts_attr_dh_nonce_params_resp_t *this); - + }; /** @@ -76,11 +76,11 @@ struct tcg_pts_attr_dh_nonce_params_resp_t { * @param dh_group Selected DH group * @param hash_algo_set Set of supported hash algorithms * @param responder_nonce DH Responder Nonce - * @param responder_pub_val DH Responder Public value + * @param responder_value DH Responder Public value */ pa_tnc_attr_t* tcg_pts_attr_dh_nonce_params_resp_create(pts_dh_group_t dh_group, pts_meas_algorithms_t hash_algo_set, - chunk_t responder_nonce, + chunk_t responder_nonce, chunk_t responder_value); /** diff --git a/src/libpts/tcg/tcg_pts_attr_file_meas.c b/src/libpts/tcg/tcg_pts_attr_file_meas.c index 1daac70e5..b9095f5be 100644 --- a/src/libpts/tcg/tcg_pts_attr_file_meas.c +++ b/src/libpts/tcg/tcg_pts_attr_file_meas.c @@ -154,7 +154,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_uint16(writer, 0); } - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_file_meas.h b/src/libpts/tcg/tcg_pts_attr_file_meas.h index c432ba9a9..8d50cd9c6 100644 --- a/src/libpts/tcg/tcg_pts_attr_file_meas.h +++ b/src/libpts/tcg/tcg_pts_attr_file_meas.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_file_meas tcg_pts_attr_file_meas - * @{ @ingroup tcg_pts_attr_file_meas + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_FILE_MEAS_H_ @@ -38,19 +38,19 @@ struct tcg_pts_attr_file_meas_t { * Public PA-TNC attribute interface */ pa_tnc_attr_t pa_tnc_attribute; - + /** * Get PTS File Measurements * * @return PTS File Measurements */ pts_file_meas_t* (*get_measurements)(tcg_pts_attr_file_meas_t *this); - + }; /** * Creates an tcg_pts_attr_file_meas_t object - * + * * @param measurements PTS File Measurements */ pa_tnc_attr_t* tcg_pts_attr_file_meas_create(pts_file_meas_t *measurements); diff --git a/src/libpts/tcg/tcg_pts_attr_gen_attest_evid.c b/src/libpts/tcg/tcg_pts_attr_gen_attest_evid.c index 9103e06b2..f263747a3 100644 --- a/src/libpts/tcg/tcg_pts_attr_gen_attest_evid.c +++ b/src/libpts/tcg/tcg_pts_attr_gen_attest_evid.c @@ -106,7 +106,7 @@ METHOD(pa_tnc_attr_t, build, void, writer = bio_writer_create(PTS_GEN_ATTEST_EVID_SIZE); writer->write_uint32 (writer, PTS_GEN_ATTEST_EVID_RESERVED); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_gen_attest_evid.h b/src/libpts/tcg/tcg_pts_attr_gen_attest_evid.h index 0a65f2143..88f070406 100644 --- a/src/libpts/tcg/tcg_pts_attr_gen_attest_evid.h +++ b/src/libpts/tcg/tcg_pts_attr_gen_attest_evid.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_gen_attest_evid tcg_pts_attr_gen_attest_evid - * @{ @ingroup tcg_pts_attr_gen_attest_evid + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_GEN_ATTEST_EVID_H_ diff --git a/src/libpts/tcg/tcg_pts_attr_get_aik.c b/src/libpts/tcg/tcg_pts_attr_get_aik.c index 6f35f5419..cf944d2a9 100644 --- a/src/libpts/tcg/tcg_pts_attr_get_aik.c +++ b/src/libpts/tcg/tcg_pts_attr_get_aik.c @@ -103,7 +103,7 @@ METHOD(pa_tnc_attr_t, build, void, writer = bio_writer_create(PTS_GET_AIK_SIZE); writer->write_uint32 (writer, PTS_GET_AIK_RESERVED); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_get_aik.h b/src/libpts/tcg/tcg_pts_attr_get_aik.h index e5c74b4dc..aca890a20 100644 --- a/src/libpts/tcg/tcg_pts_attr_get_aik.h +++ b/src/libpts/tcg/tcg_pts_attr_get_aik.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_get_aik tcg_pts_attr_get_aik - * @{ @ingroup tcg_pts_attr_get_aik + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_GET_AIK_H_ diff --git a/src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.c b/src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.c index 4dd64e3a7..647c426ed 100644 --- a/src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.c +++ b/src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.c @@ -106,7 +106,7 @@ METHOD(pa_tnc_attr_t, build, void, writer = bio_writer_create(PTS_GET_TPM_VER_INFO_SIZE); writer->write_uint32 (writer, PTS_GET_TPM_VER_INFO_RESERVED); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.h b/src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.h index 1b693402a..360049690 100644 --- a/src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.h +++ b/src/libpts/tcg/tcg_pts_attr_get_tpm_version_info.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_get_tpm_version_info tcg_pts_attr_get_tpm_version_info - * @{ @ingroup tcg_pts_attr_get_tpm_version_info + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_GET_TPM_VERSION_INFO_H_ diff --git a/src/libpts/tcg/tcg_pts_attr_meas_algo.c b/src/libpts/tcg/tcg_pts_attr_meas_algo.c index abef45bdd..a4dac9070 100644 --- a/src/libpts/tcg/tcg_pts_attr_meas_algo.c +++ b/src/libpts/tcg/tcg_pts_attr_meas_algo.c @@ -109,7 +109,7 @@ METHOD(pa_tnc_attr_t, build, void, writer = bio_writer_create(PTS_MEAS_ALGO_SIZE); writer->write_uint16(writer, PTS_MEAS_ALGO_RESERVED); writer->write_uint16(writer, this->algorithms); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_meas_algo.h b/src/libpts/tcg/tcg_pts_attr_meas_algo.h index 885e2c16b..758100bbc 100644 --- a/src/libpts/tcg/tcg_pts_attr_meas_algo.h +++ b/src/libpts/tcg/tcg_pts_attr_meas_algo.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_meas_algo tcg_pts_attr_meas_algo - * @{ @ingroup tcg_pts_attr_meas_algo + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_MEAS_ALGO_H_ diff --git a/src/libpts/tcg/tcg_pts_attr_proto_caps.c b/src/libpts/tcg/tcg_pts_attr_proto_caps.c index 360883282..6473ea808 100644 --- a/src/libpts/tcg/tcg_pts_attr_proto_caps.c +++ b/src/libpts/tcg/tcg_pts_attr_proto_caps.c @@ -110,7 +110,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_uint16(writer, PTS_PROTO_CAPS_RESERVED); writer->write_uint16(writer, this->flags); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_proto_caps.h b/src/libpts/tcg/tcg_pts_attr_proto_caps.h index 15cfbc7cb..cc59f4ef1 100644 --- a/src/libpts/tcg/tcg_pts_attr_proto_caps.h +++ b/src/libpts/tcg/tcg_pts_attr_proto_caps.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_proto_caps tcg_pts_attr_proto_caps - * @{ @ingroup tcg_pts_attr_proto_caps + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_PROTO_CAPS_H_ diff --git a/src/libpts/tcg/tcg_pts_attr_req_file_meas.c b/src/libpts/tcg/tcg_pts_attr_req_file_meas.c index 8b4bfe54d..f0bc7cf60 100644 --- a/src/libpts/tcg/tcg_pts_attr_req_file_meas.c +++ b/src/libpts/tcg/tcg_pts_attr_req_file_meas.c @@ -143,7 +143,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_uint16(writer, this->request_id); writer->write_uint32(writer, this->delimiter); writer->write_data (writer, pathname); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_req_file_meas.h b/src/libpts/tcg/tcg_pts_attr_req_file_meas.h index 19d189eff..85a6b9a43 100644 --- a/src/libpts/tcg/tcg_pts_attr_req_file_meas.h +++ b/src/libpts/tcg/tcg_pts_attr_req_file_meas.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_req_file_meas tcg_pts_attr_req_file_meas - * @{ @ingroup tcg_pts_attr_req_file_meas + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_REQ_FILE_MEAS_H_ @@ -36,7 +36,7 @@ struct tcg_pts_attr_req_file_meas_t { * Public PA-TNC attribute interface */ pa_tnc_attr_t pa_tnc_attribute; - + /** * Get flag for PTS Request File Measurement * @@ -50,7 +50,6 @@ struct tcg_pts_attr_req_file_meas_t { * @return Request ID */ u_int16_t (*get_request_id)(tcg_pts_attr_req_file_meas_t *this); - /** * Get Delimiter @@ -58,19 +57,19 @@ struct tcg_pts_attr_req_file_meas_t { * @return UTF-8 encoding of a Delimiter Character */ u_int32_t (*get_delimiter)(tcg_pts_attr_req_file_meas_t *this); - + /** * Get Fully Qualified File Pathname * * @return Pathname */ char* (*get_pathname)(tcg_pts_attr_req_file_meas_t *this); - + }; /** * Creates an tcg_pts_attr_req_file_meas_t object - * + * * @param directory_flag Directory Contents Flag * @param request_id Request ID * @param delimiter Delimiter Character diff --git a/src/libpts/tcg/tcg_pts_attr_req_file_meta.c b/src/libpts/tcg/tcg_pts_attr_req_file_meta.c index ff5581435..e475cd35b 100644 --- a/src/libpts/tcg/tcg_pts_attr_req_file_meta.c +++ b/src/libpts/tcg/tcg_pts_attr_req_file_meta.c @@ -136,7 +136,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_uint16(writer, PTS_REQ_FILE_META_RESERVED); writer->write_data (writer, pathname); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_req_file_meta.h b/src/libpts/tcg/tcg_pts_attr_req_file_meta.h index 7620c50ab..311418be2 100644 --- a/src/libpts/tcg/tcg_pts_attr_req_file_meta.h +++ b/src/libpts/tcg/tcg_pts_attr_req_file_meta.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_req_file_meta tcg_pts_attr_req_file_meta - * @{ @ingroup tcg_pts_attr_req_file_meta + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_REQ_FILE_META_H_ @@ -36,7 +36,7 @@ struct tcg_pts_attr_req_file_meta_t { * Public PA-TNC attribute interface */ pa_tnc_attr_t pa_tnc_attribute; - + /** * Get directory flag for PTS Request File Metadata * @@ -50,19 +50,19 @@ struct tcg_pts_attr_req_file_meta_t { * @return UTF-8 encoding of a Delimiter Character */ u_int8_t (*get_delimiter)(tcg_pts_attr_req_file_meta_t *this); - + /** * Get Fully Qualified File Pathname * * @return Pathname */ char* (*get_pathname)(tcg_pts_attr_req_file_meta_t *this); - + }; /** * Creates an tcg_pts_attr_req_file_meta_t object - * + * * @param directory_flag Directory Contents Flag * @param delimiter Delimiter Character * @param pathname File Pathname diff --git a/src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.c b/src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.c index 8bb43aef8..5249fa2ad 100644 --- a/src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.c +++ b/src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.c @@ -183,7 +183,7 @@ METHOD(pa_tnc_attr_t, build, void, } enumerator->destroy(enumerator); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.h b/src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.h index 031955aca..749413c2e 100644 --- a/src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.h +++ b/src/libpts/tcg/tcg_pts_attr_req_func_comp_evid.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_req_func_comp_evid tcg_pts_attr_req_func_comp_evid - * @{ @ingroup tcg_pts_attr_req_func_comp_evid + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_REQ_FUNC_COMP_EVID_H_ @@ -37,7 +37,7 @@ struct tcg_pts_attr_req_func_comp_evid_t { * Public PA-TNC attribute interface */ pa_tnc_attr_t pa_tnc_attribute; - + /** * Add a component to the Functional Component Evidence Request * @@ -62,7 +62,7 @@ struct tcg_pts_attr_req_func_comp_evid_t { * @return Entry enumerator */ enumerator_t* (*create_enumerator)(tcg_pts_attr_req_func_comp_evid_t *this); - + }; /** diff --git a/src/libpts/tcg/tcg_pts_attr_simple_comp_evid.c b/src/libpts/tcg/tcg_pts_attr_simple_comp_evid.c index c659443b7..40f380ab4 100644 --- a/src/libpts/tcg/tcg_pts_attr_simple_comp_evid.c +++ b/src/libpts/tcg/tcg_pts_attr_simple_comp_evid.c @@ -242,7 +242,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_data(writer, measurement); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_simple_comp_evid.h b/src/libpts/tcg/tcg_pts_attr_simple_comp_evid.h index 3a80904c8..494418261 100644 --- a/src/libpts/tcg/tcg_pts_attr_simple_comp_evid.h +++ b/src/libpts/tcg/tcg_pts_attr_simple_comp_evid.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_simple_comp_evid tcg_pts_attr_simple_comp_evid - * @{ @ingroup tcg_pts_attr_simple_comp_evid + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_SIMPLE_COMP_EVID_H_ @@ -24,7 +24,7 @@ typedef struct tcg_pts_attr_simple_comp_evid_t tcg_pts_attr_simple_comp_evid_t; #include "tcg_attr.h" -#include "pts/components/pts_comp_evidence.h" +#include "pts/components/pts_comp_evidence.h" #include "pa_tnc/pa_tnc_attr.h" /** @@ -44,12 +44,12 @@ struct tcg_pts_attr_simple_comp_evid_t { * @return Component Evidence */ pts_comp_evidence_t* (*get_comp_evidence)(tcg_pts_attr_simple_comp_evid_t *this); - + }; /** * Creates an tcg_pts_attr_simple_comp_evid_t object - * + * * @param evid Component Evidence */ pa_tnc_attr_t* tcg_pts_attr_simple_comp_evid_create(pts_comp_evidence_t *evid); diff --git a/src/libpts/tcg/tcg_pts_attr_simple_evid_final.c b/src/libpts/tcg/tcg_pts_attr_simple_evid_final.c index 8c76651d6..baadd943f 100644 --- a/src/libpts/tcg/tcg_pts_attr_simple_evid_final.c +++ b/src/libpts/tcg/tcg_pts_attr_simple_evid_final.c @@ -194,7 +194,7 @@ METHOD(pa_tnc_attr_t, build, void, writer->write_data (writer, this->evid_sig); } - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_simple_evid_final.h b/src/libpts/tcg/tcg_pts_attr_simple_evid_final.h index 3d98bfce7..6778afbdc 100644 --- a/src/libpts/tcg/tcg_pts_attr_simple_evid_final.h +++ b/src/libpts/tcg/tcg_pts_attr_simple_evid_final.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_simple_evid_final tcg_pts_attr_simple_evid_final - * @{ @ingroup tcg_pts_attr_simple_evid_final + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_SIMPLE_EVID_FINAL_H_ @@ -44,27 +44,29 @@ struct tcg_pts_attr_simple_evid_final_t { * @param comp_hash_algo Optional Composite Hash Algorithm * @param pcr_comp Optional PCR Composite * @param tpm_quote sig Optional TPM Quote Signature - * @return PTS_SIMPLE_EVID_FINAL flags + * @return PTS_SIMPLE_EVID_FINAL flags */ u_int8_t (*get_quote_info)(tcg_pts_attr_simple_evid_final_t *this, pts_meas_algorithms_t *comp_hash_algo, chunk_t *pcr_comp, chunk_t *tpm_quote_sig); - + /** * Get Optional Evidence Signature * - * @evid_sig Optional Evidence Signature + * @param evid_sig Optional Evidence Signature * @return TRUE if Evidence Signature is available */ - bool (*get_evid_sig)(tcg_pts_attr_simple_evid_final_t *this, chunk_t *evid_sig); + bool (*get_evid_sig)(tcg_pts_attr_simple_evid_final_t *this, + chunk_t *evid_sig); /** * Set Optional Evidence Signature * - * @evid_sig Optional Evidence Signature + * @param vid_sig Optional Evidence Signature */ - void (*set_evid_sig)(tcg_pts_attr_simple_evid_final_t *this, chunk_t evid_sig); - + void (*set_evid_sig)(tcg_pts_attr_simple_evid_final_t *this, + chunk_t evid_sig); + }; /** diff --git a/src/libpts/tcg/tcg_pts_attr_tpm_version_info.c b/src/libpts/tcg/tcg_pts_attr_tpm_version_info.c index 5143e1676..b776cb662 100644 --- a/src/libpts/tcg/tcg_pts_attr_tpm_version_info.c +++ b/src/libpts/tcg/tcg_pts_attr_tpm_version_info.c @@ -110,7 +110,7 @@ METHOD(pa_tnc_attr_t, build, void, writer = bio_writer_create(PTS_TPM_VER_INFO_SIZE); writer->write_data(writer, this->tpm_version_info); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_tpm_version_info.h b/src/libpts/tcg/tcg_pts_attr_tpm_version_info.h index 2c12bb068..4ac18fb9e 100644 --- a/src/libpts/tcg/tcg_pts_attr_tpm_version_info.h +++ b/src/libpts/tcg/tcg_pts_attr_tpm_version_info.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_tpm_version_info tcg_pts_attr_tpm_version_info - * @{ @ingroup tcg_pts_attr_tpm_version_info + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_TPM_VERSION_INFO_H_ @@ -36,7 +36,7 @@ struct tcg_pts_attr_tpm_version_info_t { * Public PA-TNC attribute interface */ pa_tnc_attr_t pa_tnc_attribute; - + /** * Get TPM Version Info * @@ -55,7 +55,7 @@ struct tcg_pts_attr_tpm_version_info_t { /** * Creates an tcg_pts_attr_tpm_version_info_t object - * + * * @param tpm_version_info TPM version info */ pa_tnc_attr_t* tcg_pts_attr_tpm_version_info_create(chunk_t tpm_version_info); diff --git a/src/libpts/tcg/tcg_pts_attr_unix_file_meta.c b/src/libpts/tcg/tcg_pts_attr_unix_file_meta.c index 56686d8ca..f96371b8b 100644 --- a/src/libpts/tcg/tcg_pts_attr_unix_file_meta.c +++ b/src/libpts/tcg/tcg_pts_attr_unix_file_meta.c @@ -166,7 +166,7 @@ METHOD(pa_tnc_attr_t, build, void, } enumerator->destroy(enumerator); - this->value = chunk_clone(writer->get_buf(writer)); + this->value = writer->extract_buf(writer); writer->destroy(writer); } diff --git a/src/libpts/tcg/tcg_pts_attr_unix_file_meta.h b/src/libpts/tcg/tcg_pts_attr_unix_file_meta.h index 8a594eab5..ad9794b45 100644 --- a/src/libpts/tcg/tcg_pts_attr_unix_file_meta.h +++ b/src/libpts/tcg/tcg_pts_attr_unix_file_meta.h @@ -15,7 +15,7 @@ /** * @defgroup tcg_pts_attr_unix_file_meta tcg_pts_attr_unix_file_meta - * @{ @ingroup tcg_pts_attr_unix_file_meta + * @{ @ingroup tcg_attr */ #ifndef TCG_PTS_ATTR_UNIX_FILE_META_H_ @@ -38,19 +38,19 @@ struct tcg_pts_attr_file_meta_t { * Public PA-TNC attribute interface */ pa_tnc_attr_t pa_tnc_attribute; - + /** * Get PTS File Metadata * * @return PTS File Metadata */ pts_file_meta_t* (*get_metadata)(tcg_pts_attr_file_meta_t *this); - + }; /** * Creates an tcg_pts_attr_file_meta_t object - * + * * @param metadata PTS File Metadata */ pa_tnc_attr_t* tcg_pts_attr_unix_file_meta_create(pts_file_meta_t *metadata); diff --git a/src/libpttls/Makefile.am b/src/libpttls/Makefile.am new file mode 100644 index 000000000..48123181b --- /dev/null +++ b/src/libpttls/Makefile.am @@ -0,0 +1,12 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libtls \ + -I$(top_srcdir)/src/libtncif -I$(top_srcdir)/src/libtnccs + +ipseclib_LTLIBRARIES = libpttls.la +libpttls_la_LIBADD = $(top_builddir)/src/libtls/libtls.la +libpttls_la_SOURCES = pt_tls.c pt_tls.h \ + pt_tls_client.c pt_tls_client.h \ + pt_tls_server.c pt_tls_server.h \ + pt_tls_dispatcher.c pt_tls_dispatcher.h \ + sasl/sasl_plain/sasl_plain.c sasl/sasl_plain/sasl_plain.h \ + sasl/sasl_mechanism.c sasl/sasl_mechanism.h diff --git a/src/libpttls/pt_tls.c b/src/libpttls/pt_tls.c new file mode 100644 index 000000000..0fee343b8 --- /dev/null +++ b/src/libpttls/pt_tls.c @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * 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 "pt_tls.h" + +#include <utils/debug.h> + +/* + * PT-TNC Message format: + * 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | Message Type Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Message Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Message Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Message Identifier | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Message Value (e.g. PB-TNC Batch) . . . | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/** + * Read a chunk of data from TLS, returning a reader for it + */ +static bio_reader_t* read_tls(tls_socket_t *tls, size_t len) +{ + ssize_t got, total = 0; + char *buf; + + buf = malloc(len); + while (total < len) + { + got = tls->read(tls, buf + total, len - total, TRUE); + if (got <= 0) + { + free(buf); + return NULL; + } + total += got; + } + return bio_reader_create_own(chunk_create(buf, len)); +} + +/** + * Read a PT-TLS message, return header data + */ +bio_reader_t* pt_tls_read(tls_socket_t *tls, u_int32_t *vendor, + u_int32_t *type, u_int32_t *identifier) +{ + bio_reader_t *reader; + u_int32_t len; + u_int8_t reserved; + + reader = read_tls(tls, PT_TLS_HEADER_LEN); + if (!reader) + { + return NULL; + } + if (!reader->read_uint8(reader, &reserved) || + !reader->read_uint24(reader, vendor) || + !reader->read_uint32(reader, type) || + !reader->read_uint32(reader, &len) || + !reader->read_uint32(reader, identifier)) + { + reader->destroy(reader); + return NULL; + } + reader->destroy(reader); + + if (len < PT_TLS_HEADER_LEN) + { + DBG1(DBG_TNC, "received short PT-TLS header (%d bytes)", len); + return NULL; + } + return read_tls(tls, len - PT_TLS_HEADER_LEN); +} + +/** + * Prepend a PT-TLS header to a writer, send data, destroy writer + */ +bool pt_tls_write(tls_socket_t *tls, bio_writer_t *writer, + pt_tls_message_type_t type, u_int32_t identifier) +{ + bio_writer_t *header; + ssize_t len; + chunk_t data; + + data = writer->get_buf(writer); + len = PT_TLS_HEADER_LEN + data.len; + header = bio_writer_create(len); + header->write_uint8(header, 0); + header->write_uint24(header, 0); + header->write_uint32(header, type); + header->write_uint32(header, len); + header->write_uint32(header, identifier); + + header->write_data(header, data); + writer->destroy(writer); + + data = header->get_buf(header); + len = tls->write(tls, data.ptr, data.len); + header->destroy(header); + + return len == data.len; +} diff --git a/src/libpttls/pt_tls.h b/src/libpttls/pt_tls.h new file mode 100644 index 000000000..cb8bde05c --- /dev/null +++ b/src/libpttls/pt_tls.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * 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 pt_tls pt_tls + * + * @addtogroup pt_tls + * @{ + */ + +#ifndef PT_TLS_H_ +#define PT_TLS_H_ + +#include <bio/bio_reader.h> +#include <bio/bio_writer.h> +#include <tls_socket.h> + +/** + * PT-TLS version we support + */ +#define PT_TLS_VERSION 1 + +/** + * Length of a PT-TLS header + */ +#define PT_TLS_HEADER_LEN 16 + +typedef enum pt_tls_message_type_t pt_tls_message_type_t; +typedef enum pt_tls_sasl_result_t pt_tls_sasl_result_t; +typedef enum pt_tls_auth_t pt_tls_auth_t; + +/** + * Message types, as defined by NEA PT-TLS + */ +enum pt_tls_message_type_t { + PT_TLS_EXPERIMENTAL = 0, + PT_TLS_VERSION_REQUEST = 1, + PT_TLS_VERSION_RESPONSE = 2, + PT_TLS_SASL_MECHS = 3, + PT_TLS_SASL_MECH_SELECTION = 4, + PT_TLS_SASL_AUTH_DATA = 5, + PT_TLS_SASL_RESULT = 6, + PT_TLS_PB_TNC_BATCH = 7, + PT_TLS_ERROR = 8, +}; + +/** + * Result code for a single SASL mechansim, as sent in PT_TLS_SASL_RESULT + */ +enum pt_tls_sasl_result_t { + PT_TLS_SASL_RESULT_SUCCESS = 0, + PT_TLS_SASL_RESULT_FAILURE = 1, + PT_TLS_SASL_RESULT_ABORT = 2, + PT_TLS_SASL_RESULT_MECH_FAILURE = 3, +}; + +/** + * Client authentication to require as PT-TLS server. + */ +enum pt_tls_auth_t { + /** don't require TLS client certificate or request SASL authentication */ + PT_TLS_AUTH_NONE, + /** require TLS certificate authentication, no SASL */ + PT_TLS_AUTH_TLS, + /** do SASL regardless of TLS certificate authentication */ + PT_TLS_AUTH_SASL, + /* if client does not authenticate with a TLS certificate, request SASL */ + PT_TLS_AUTH_TLS_OR_SASL, + /* require both, TLS certificate authentication and SASL */ + PT_TLS_AUTH_TLS_AND_SASL, +}; + +/** + * Read a PT-TLS message, create reader over Message Value. + * + * @param tls TLS socket to read from + * @param vendor receives Message Type Vendor ID from header + * @param type receives Message Type from header + * @param identifier receives Message Identifer + * @return reader over message value, NULL on error + */ +bio_reader_t* pt_tls_read(tls_socket_t *tls, u_int32_t *vendor, + u_int32_t *type, u_int32_t *identifier); + +/** + * Prepend a PT-TLS header to a writer, send data, destroy writer. + * + * @param tls TLS socket to write to + * @param writer prepared Message value to write + * @param type Message Type to write + * @param identifier Message Identifier to write + * @return TRUE if data written successfully + */ +bool pt_tls_write(tls_socket_t *tls, bio_writer_t *writer, + pt_tls_message_type_t type, u_int32_t identifier); + +#endif /** PT_TLS_H_ @}*/ diff --git a/src/libpttls/pt_tls_client.c b/src/libpttls/pt_tls_client.c new file mode 100644 index 000000000..a01da3939 --- /dev/null +++ b/src/libpttls/pt_tls_client.c @@ -0,0 +1,495 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * 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 "pt_tls_client.h" +#include "pt_tls.h" + +#include <sasl/sasl_mechanism.h> + +#include <tls_socket.h> +#include <utils/debug.h> + +#include <errno.h> +#include <stdio.h> +#include <unistd.h> + +typedef struct private_pt_tls_client_t private_pt_tls_client_t; + +/** + * Private data of an pt_tls_client_t object. + */ +struct private_pt_tls_client_t { + + /** + * Public pt_tls_client_t interface. + */ + pt_tls_client_t public; + + /** + * TLS secured socket used by PT-TLS + */ + tls_socket_t *tls; + + /** + * Server address/port + */ + host_t *address; + + /** + * Server identity + */ + identification_t *server; + + /** + * Client authentication identity + */ + identification_t *client; + + /** + * Current PT-TLS message identifier + */ + u_int32_t identifier; +}; + +/** + * Establish TLS secured TCP connection to TNC server + */ +static bool make_connection(private_pt_tls_client_t *this) +{ + int fd; + + fd = socket(this->address->get_family(this->address), SOCK_STREAM, 0); + if (fd == -1) + { + DBG1(DBG_TNC, "opening PT-TLS socket failed: %s", strerror(errno)); + return FALSE; + } + if (connect(fd, this->address->get_sockaddr(this->address), + *this->address->get_sockaddr_len(this->address)) == -1) + { + DBG1(DBG_TNC, "connecting to PT-TLS server failed: %s", strerror(errno)); + close(fd); + return FALSE; + } + + this->tls = tls_socket_create(FALSE, this->server, this->client, fd, NULL); + if (!this->tls) + { + close(fd); + return FALSE; + } + return TRUE; +} + +/** + * Negotiate PT-TLS version + */ +static bool negotiate_version(private_pt_tls_client_t *this) +{ + bio_writer_t *writer; + bio_reader_t *reader; + u_int32_t type, vendor, identifier, reserved; + u_int8_t version; + + DBG1(DBG_TNC, "sending offer for PT-TLS version %d", PT_TLS_VERSION); + + writer = bio_writer_create(4); + writer->write_uint8(writer, 0); + writer->write_uint8(writer, PT_TLS_VERSION); + writer->write_uint8(writer, PT_TLS_VERSION); + writer->write_uint8(writer, PT_TLS_VERSION); + if (!pt_tls_write(this->tls, writer, PT_TLS_VERSION_REQUEST, + this->identifier++)) + { + return FALSE; + } + + reader = pt_tls_read(this->tls, &vendor, &type, &identifier); + if (!reader) + { + return FALSE; + } + if (vendor != 0 || type != PT_TLS_VERSION_RESPONSE || + !reader->read_uint24(reader, &reserved) || + !reader->read_uint8(reader, &version) || + version != PT_TLS_VERSION) + { + DBG1(DBG_TNC, "PT-TLS version negotiation failed"); + reader->destroy(reader); + return FALSE; + } + reader->destroy(reader); + return TRUE; +} + +/** + * Run a SASL mechanism + */ +static status_t do_sasl(private_pt_tls_client_t *this, sasl_mechanism_t *sasl) +{ + u_int32_t type, vendor, identifier; + u_int8_t result; + bio_reader_t *reader; + bio_writer_t *writer; + chunk_t data; + + writer = bio_writer_create(32); + writer->write_data8(writer, chunk_from_str(sasl->get_name(sasl))); + switch (sasl->build(sasl, &data)) + { + case INVALID_STATE: + break; + case NEED_MORE: + writer->write_data(writer, data); + free(data.ptr); + break; + case SUCCESS: + /* shouldn't happen */ + free(data.ptr); + /* FALL */ + case FAILED: + default: + writer->destroy(writer); + return FAILED; + } + if (!pt_tls_write(this->tls, writer, PT_TLS_SASL_MECH_SELECTION, + this->identifier++)) + { + return FAILED; + } + while (TRUE) + { + reader = pt_tls_read(this->tls, &vendor, &type, &identifier); + if (!reader) + { + return FAILED; + } + if (vendor != 0) + { + reader->destroy(reader); + return FAILED; + } + switch (type) + { + case PT_TLS_SASL_AUTH_DATA: + switch (sasl->process(sasl, reader->peek(reader))) + { + case NEED_MORE: + reader->destroy(reader); + break; + case SUCCESS: + /* should not happen, as it would come in a RESULT */ + case FAILED: + default: + reader->destroy(reader); + return FAILED; + } + break; + case PT_TLS_SASL_RESULT: + if (!reader->read_uint8(reader, &result)) + { + reader->destroy(reader); + return FAILED; + } + switch (result) + { + case PT_TLS_SASL_RESULT_ABORT: + DBG1(DBG_TNC, "received SASL abort result"); + reader->destroy(reader); + return FAILED; + case PT_TLS_SASL_RESULT_SUCCESS: + DBG1(DBG_TNC, "received SASL success result"); + switch (sasl->process(sasl, reader->peek(reader))) + { + case SUCCESS: + reader->destroy(reader); + return SUCCESS; + case NEED_MORE: + /* inacceptable, it won't get more. FALL */ + case FAILED: + default: + reader->destroy(reader); + return FAILED; + } + break; + case PT_TLS_SASL_RESULT_MECH_FAILURE: + case PT_TLS_SASL_RESULT_FAILURE: + DBG1(DBG_TNC, "received SASL failure result"); + /* non-fatal failure, try again */ + reader->destroy(reader); + return NEED_MORE; + } + default: + return FAILED; + } + + writer = bio_writer_create(32); + switch (sasl->build(sasl, &data)) + { + case INVALID_STATE: + break; + case SUCCESS: + /* shoudln't happen, continue until we get a result */ + case NEED_MORE: + writer->write_data(writer, data); + free(data.ptr); + break; + case FAILED: + default: + writer->destroy(writer); + return FAILED; + } + if (!pt_tls_write(this->tls, writer, PT_TLS_SASL_AUTH_DATA, + this->identifier++)) + { + return FAILED; + } + } +} + +/** + * Read SASL mechanism list, select and run mechanism + */ +static status_t select_and_do_sasl(private_pt_tls_client_t *this) +{ + bio_reader_t *reader; + sasl_mechanism_t *sasl = NULL; + u_int32_t type, vendor, identifier; + u_int8_t len; + chunk_t chunk; + char buf[21]; + status_t status = NEED_MORE; + + reader = pt_tls_read(this->tls, &vendor, &type, &identifier); + if (!reader) + { + return FAILED; + } + if (vendor != 0 || type != PT_TLS_SASL_MECHS) + { + reader->destroy(reader); + return FAILED; + } + if (!reader->remaining(reader)) + { /* mechanism list empty, SASL completed */ + DBG1(DBG_TNC, "PT-TLS authentication complete"); + reader->destroy(reader); + return SUCCESS; + } + while (reader->remaining(reader)) + { + if (!reader->read_uint8(reader, &len) || + !reader->read_data(reader, len & 0x1F, &chunk)) + { + reader->destroy(reader); + return FAILED; + } + snprintf(buf, sizeof(buf), "%.*s", (int)chunk.len, chunk.ptr); + sasl = sasl_mechanism_create(buf, this->client); + if (sasl) + { + break; + } + } + reader->destroy(reader); + + if (!sasl) + { + /* TODO: send PT-TLS error (5) */ + return FAILED; + } + while (status == NEED_MORE) + { + status = do_sasl(this, sasl); + } + sasl->destroy(sasl); + if (status == SUCCESS) + { /* continue until we receive empty SASL mechanism list */ + return NEED_MORE; + } + return FAILED; +} + +/** + * Authenticate session using SASL + */ +static bool authenticate(private_pt_tls_client_t *this) +{ + while (TRUE) + { + switch (select_and_do_sasl(this)) + { + case NEED_MORE: + continue; + case SUCCESS: + return TRUE; + case FAILED: + default: + return FALSE; + } + } +} + +/** + * Perform assessment + */ +static bool assess(private_pt_tls_client_t *this, tls_t *tnccs) +{ + while (TRUE) + { + bio_writer_t *writer; + bio_reader_t *reader; + u_int32_t vendor, type, identifier; + chunk_t data; + + writer = bio_writer_create(32); + while (TRUE) + { + char buf[2048]; + size_t buflen, msglen; + + buflen = sizeof(buf); + switch (tnccs->build(tnccs, buf, &buflen, &msglen)) + { + case SUCCESS: + writer->destroy(writer); + return tnccs->is_complete(tnccs); + case FAILED: + default: + writer->destroy(writer); + return FALSE; + case INVALID_STATE: + writer->destroy(writer); + break; + case NEED_MORE: + writer->write_data(writer, chunk_create(buf, buflen)); + continue; + case ALREADY_DONE: + writer->write_data(writer, chunk_create(buf, buflen)); + if (!pt_tls_write(this->tls, writer, PT_TLS_PB_TNC_BATCH, + this->identifier++)) + { + return FALSE; + } + writer = bio_writer_create(32); + continue; + } + break; + } + + reader = pt_tls_read(this->tls, &vendor, &type, &identifier); + if (!reader) + { + return FALSE; + } + if (vendor == 0) + { + if (type == PT_TLS_ERROR) + { + DBG1(DBG_TNC, "received PT-TLS error"); + reader->destroy(reader); + return FALSE; + } + if (type != PT_TLS_PB_TNC_BATCH) + { + DBG1(DBG_TNC, "unexpected PT-TLS message: %d", type); + reader->destroy(reader); + return FALSE; + } + data = reader->peek(reader); + switch (tnccs->process(tnccs, data.ptr, data.len)) + { + case SUCCESS: + reader->destroy(reader); + return tnccs->is_complete(tnccs); + case FAILED: + default: + reader->destroy(reader); + return FALSE; + case NEED_MORE: + break; + } + } + else + { + DBG1(DBG_TNC, "ignoring vendor specific PT-TLS message"); + } + reader->destroy(reader); + } +} + +METHOD(pt_tls_client_t, run_assessment, status_t, + private_pt_tls_client_t *this, tnccs_t *tnccs) +{ + if (!this->tls) + { + if (!make_connection(this)) + { + return FAILED; + } + } + if (!negotiate_version(this)) + { + return FAILED; + } + if (!authenticate(this)) + { + return FAILED; + } + if (!assess(this, (tls_t*)tnccs)) + { + return FAILED; + } + return SUCCESS; +} + + +METHOD(pt_tls_client_t, destroy, void, + private_pt_tls_client_t *this) +{ + if (this->tls) + { + int fd; + + fd = this->tls->get_fd(this->tls); + this->tls->destroy(this->tls); + close(fd); + } + this->address->destroy(this->address); + this->server->destroy(this->server); + this->client->destroy(this->client); + free(this); +} + +/** + * See header + */ +pt_tls_client_t *pt_tls_client_create(host_t *address, identification_t *server, + identification_t *client) +{ + private_pt_tls_client_t *this; + + INIT(this, + .public = { + .run_assessment = _run_assessment, + .destroy = _destroy, + }, + .address = address, + .server = server, + .client = client, + ); + + return &this->public; +} diff --git a/src/libpttls/pt_tls_client.h b/src/libpttls/pt_tls_client.h new file mode 100644 index 000000000..1d418d181 --- /dev/null +++ b/src/libpttls/pt_tls_client.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * 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 pt_tls_client pt_tls_client + * @{ @ingroup pt_tls + */ + +#ifndef PT_TLS_CLIENT_H_ +#define PT_TLS_CLIENT_H_ + +#include <networking/host.h> +#include <utils/identification.h> + +#include <tnc/tnccs/tnccs.h> + +typedef struct pt_tls_client_t pt_tls_client_t; + +/** + * IF-T for TLS aka PT-TLS transport client. + */ +struct pt_tls_client_t { + + /** + * Perform an assessment. + * + * @param tnccs upper layer TNC client used for assessment + * @return status of assessment + */ + status_t (*run_assessment)(pt_tls_client_t *this, tnccs_t *tnccs); + + /** + * Destroy a pt_tls_client_t. + */ + void (*destroy)(pt_tls_client_t *this); +}; + +/** + * Create a pt_tls_client instance. + * + * The client identity is used for: + * - TLS authentication if an appropirate certificate is found + * - SASL authentication if requested from the server + * + * @param address address/port to run assessments against, gets owned + * @param server server identity to use for authentication, gets owned + * @param client client identity to use for authentication, gets owned + * @return PT-TLS context + */ +pt_tls_client_t *pt_tls_client_create(host_t *address, identification_t *server, + identification_t *client); + +#endif /** PT_TLS_CLIENT_H_ @}*/ diff --git a/src/libpttls/pt_tls_dispatcher.c b/src/libpttls/pt_tls_dispatcher.c new file mode 100644 index 000000000..469951616 --- /dev/null +++ b/src/libpttls/pt_tls_dispatcher.c @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * 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 "pt_tls_dispatcher.h" +#include "pt_tls_server.h" + +#include <threading/thread.h> +#include <utils/debug.h> +#include <processing/jobs/callback_job.h> + +#include <errno.h> +#include <string.h> +#include <unistd.h> + +typedef struct private_pt_tls_dispatcher_t private_pt_tls_dispatcher_t; + +/** + * Private data of an pt_tls_dispatcher_t object. + */ +struct private_pt_tls_dispatcher_t { + + /** + * Public pt_tls_dispatcher_t interface. + */ + pt_tls_dispatcher_t public; + + /** + * Listening socket + */ + int fd; + + /** + * Client authentication requirements + */ + pt_tls_auth_t auth; + + /** + * Server identity + */ + identification_t *server; + + /** + * Peer identity + */ + identification_t *peer; + + /** + * TNCCS protocol handler constructor + */ + pt_tls_tnccs_constructor_t *create; +}; + +/** + * Open listening server socket + */ +static bool open_socket(private_pt_tls_dispatcher_t *this, host_t *host) +{ + this->fd = socket(AF_INET, SOCK_STREAM, 0); + if (this->fd == -1) + { + DBG1(DBG_TNC, "opening PT-TLS socket failed: %s", strerror(errno)); + return FALSE; + } + if (bind(this->fd, host->get_sockaddr(host), + *host->get_sockaddr_len(host)) == -1) + { + DBG1(DBG_TNC, "binding to PT-TLS socket failed: %s", strerror(errno)); + return FALSE; + } + if (listen(this->fd, 5) == -1) + { + DBG1(DBG_TNC, "listen on PT-TLS socket failed: %s", strerror(errno)); + return FALSE; + } + return TRUE; +} + +/** + * Handle a single PT-TLS client connection + */ +static job_requeue_t handle(pt_tls_server_t *connection) +{ + while (TRUE) + { + switch (connection->handle(connection)) + { + case NEED_MORE: + continue; + case FAILED: + case SUCCESS: + default: + break; + } + break; + } + return JOB_REQUEUE_NONE; +} + +/** + * Clean up connection state + */ +static void cleanup(pt_tls_server_t *connection) +{ + int fd; + + fd = connection->get_fd(connection); + connection->destroy(connection); + close(fd); +} + +METHOD(pt_tls_dispatcher_t, dispatch, void, + private_pt_tls_dispatcher_t *this, + pt_tls_tnccs_constructor_t *create) +{ + while (TRUE) + { + pt_tls_server_t *connection; + tnccs_t *tnccs; + bool old; + int fd; + + old = thread_cancelability(TRUE); + fd = accept(this->fd, NULL, NULL); + thread_cancelability(old); + if (fd == -1) + { + DBG1(DBG_TNC, "accepting PT-TLS failed: %s", strerror(errno)); + continue; + } + + tnccs = create(this->server, this->peer); + if (!tnccs) + { + close(fd); + continue; + } + connection = pt_tls_server_create(this->server, fd, this->auth, tnccs); + if (!connection) + { + close(fd); + continue; + } + lib->processor->queue_job(lib->processor, + (job_t*)callback_job_create_with_prio((callback_job_cb_t)handle, + connection, (void*)cleanup, + (callback_job_cancel_t)return_false, + JOB_PRIO_CRITICAL)); + } +} + +METHOD(pt_tls_dispatcher_t, destroy, void, + private_pt_tls_dispatcher_t *this) +{ + if (this->fd != -1) + { + close(this->fd); + } + this->server->destroy(this->server); + this->peer->destroy(this->peer); + free(this); +} + +/** + * See header + */ +pt_tls_dispatcher_t *pt_tls_dispatcher_create(host_t *address, + identification_t *id, pt_tls_auth_t auth) +{ + private_pt_tls_dispatcher_t *this; + + INIT(this, + .public = { + .dispatch = _dispatch, + .destroy = _destroy, + }, + .server = id, + /* we currently don't authenticate the peer, use %any identity */ + .peer = identification_create_from_encoding(ID_ANY, chunk_empty), + .fd = -1, + .auth = auth, + ); + + if (!open_socket(this, address)) + { + address->destroy(address); + destroy(this); + return NULL; + } + address->destroy(address); + + return &this->public; +} diff --git a/src/libpttls/pt_tls_dispatcher.h b/src/libpttls/pt_tls_dispatcher.h new file mode 100644 index 000000000..080197263 --- /dev/null +++ b/src/libpttls/pt_tls_dispatcher.h @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * 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 pt_tls_dispatcher pt_tls_dispatcher + * @{ @ingroup pt_tls + */ + +#ifndef PT_TLS_DISPATCHER_H_ +#define PT_TLS_DISPATCHER_H_ + +#include <networking/host.h> +#include <utils/identification.h> + +#include <tnc/tnccs/tnccs.h> + +#include "pt_tls.h" + +typedef struct pt_tls_dispatcher_t pt_tls_dispatcher_t; + +/** + * Constructor callback to create TNCCS to use within PT-TLS. + * + * @param server server identity + * @param peer peer identity + */ +typedef tnccs_t* (pt_tls_tnccs_constructor_t)(identification_t *server, + identification_t *peer); + +/** + * PT-TLS dispatcher service, handles PT-TLS connections as a server. + */ +struct pt_tls_dispatcher_t { + + /** + * Dispatch and handle PT-TLS connections. + * + * This call is blocking and a thread cancellation point. The passed + * constructor gets called for each dispatched connection. + * + * @param create TNCCS constructor function to use + */ + void (*dispatch)(pt_tls_dispatcher_t *this, + pt_tls_tnccs_constructor_t *create); + + /** + * Destroy a pt_tls_dispatcher_t. + */ + void (*destroy)(pt_tls_dispatcher_t *this); +}; + +/** + * Create a pt_tls_dispatcher instance. + * + * @param address server address with port to listen on, gets owned + * @param id TLS server identity, gets owned + * @param auth client authentication to perform + * @return dispatcher service + */ +pt_tls_dispatcher_t *pt_tls_dispatcher_create(host_t *address, + identification_t *id, pt_tls_auth_t auth); + +#endif /** PT_TLS_DISPATCHER_H_ @}*/ diff --git a/src/libpttls/pt_tls_server.c b/src/libpttls/pt_tls_server.c new file mode 100644 index 000000000..3e134f0dd --- /dev/null +++ b/src/libpttls/pt_tls_server.c @@ -0,0 +1,544 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * 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 "pt_tls_server.h" + +#include <sasl/sasl_mechanism.h> + +#include <utils/debug.h> + +typedef struct private_pt_tls_server_t private_pt_tls_server_t; + +/** + * Private data of an pt_tls_server_t object. + */ +struct private_pt_tls_server_t { + + /** + * Public pt_tls_server_t interface. + */ + pt_tls_server_t public; + + /** + * TLS protected socket + */ + tls_socket_t *tls; + + /** + * Client authentication requirements + */ + pt_tls_auth_t auth; + + enum { + /* expecting version negotiation */ + PT_TLS_SERVER_VERSION, + /* expecting an SASL exchange */ + PT_TLS_SERVER_AUTH, + /* expecting TNCCS exchange */ + PT_TLS_SERVER_TNCCS, + /* terminating state */ + PT_TLS_SERVER_END, + } state; + + /** + * Message Identifier + */ + u_int32_t identifier; + + /** + * TNCCS protocol handler, implemented as tls_t + */ + tls_t *tnccs; +}; + +/** + * Negotiate PT-TLS version + */ +static bool negotiate_version(private_pt_tls_server_t *this) +{ + bio_reader_t *reader; + bio_writer_t *writer; + u_int32_t vendor, type, identifier; + u_int8_t reserved, vmin, vmax, vpref; + + reader = pt_tls_read(this->tls, &vendor, &type, &identifier); + if (!reader) + { + return FALSE; + } + if (vendor != 0 || type != PT_TLS_VERSION_REQUEST || + !reader->read_uint8(reader, &reserved) || + !reader->read_uint8(reader, &vmin) || + !reader->read_uint8(reader, &vmax) || + !reader->read_uint8(reader, &vpref)) + { + DBG1(DBG_TNC, "PT-TLS version negotiation failed"); + reader->destroy(reader); + return FALSE; + } + reader->destroy(reader); + + if (vmin > PT_TLS_VERSION || vmax < PT_TLS_VERSION) + { + /* TODO: send error */ + return FALSE; + } + + writer = bio_writer_create(4); + writer->write_uint24(writer, 0); + writer->write_uint8(writer, PT_TLS_VERSION); + + return pt_tls_write(this->tls, writer, PT_TLS_VERSION_RESPONSE, + this->identifier++); +} + +/** + * Process SASL data, send result + */ +static status_t process_sasl(private_pt_tls_server_t *this, + sasl_mechanism_t *sasl, chunk_t data) +{ + bio_writer_t *writer; + + switch (sasl->process(sasl, data)) + { + case NEED_MORE: + return NEED_MORE; + case SUCCESS: + DBG1(DBG_TNC, "SASL %s authentication successful", + sasl->get_name(sasl)); + writer = bio_writer_create(1); + writer->write_uint8(writer, PT_TLS_SASL_RESULT_SUCCESS); + if (pt_tls_write(this->tls, writer, PT_TLS_SASL_RESULT, + this->identifier++)) + { + return SUCCESS; + } + return FAILED; + case FAILED: + default: + DBG1(DBG_TNC, "SASL %s authentication failed", + sasl->get_name(sasl)); + writer = bio_writer_create(1); + /* sending abort does not allow the client to retry */ + writer->write_uint8(writer, PT_TLS_SASL_RESULT_ABORT); + pt_tls_write(this->tls, writer, PT_TLS_SASL_RESULT, + this->identifier++); + return FAILED; + } +} + +/** + * Read a SASL message and process it + */ +static status_t read_sasl(private_pt_tls_server_t *this, + sasl_mechanism_t *sasl) +{ + u_int32_t vendor, type, identifier; + bio_reader_t *reader; + status_t status; + chunk_t data; + + reader = pt_tls_read(this->tls, &vendor, &type, &identifier); + if (!reader) + { + return FAILED; + } + if (vendor != 0 || type != PT_TLS_SASL_AUTH_DATA || + !reader->read_data(reader, reader->remaining(reader), &data)) + { + reader->destroy(reader); + return FAILED; + } + status = process_sasl(this, sasl, data); + reader->destroy(reader); + return status; +} + +/** + * Build and write SASL message, or result message + */ +static status_t write_sasl(private_pt_tls_server_t *this, + sasl_mechanism_t *sasl) +{ + bio_writer_t *writer; + chunk_t chunk; + + switch (sasl->build(sasl, &chunk)) + { + case NEED_MORE: + writer = bio_writer_create(chunk.len); + writer->write_data(writer, chunk); + free(chunk.ptr); + if (pt_tls_write(this->tls, writer, PT_TLS_SASL_AUTH_DATA, + this->identifier++)) + { + return NEED_MORE; + } + return FAILED; + case SUCCESS: + DBG1(DBG_TNC, "SASL %s authentication successful", + sasl->get_name(sasl)); + writer = bio_writer_create(1 + chunk.len); + writer->write_uint8(writer, PT_TLS_SASL_RESULT_SUCCESS); + writer->write_data(writer, chunk); + free(chunk.ptr); + if (pt_tls_write(this->tls, writer, PT_TLS_SASL_RESULT, + this->identifier++)) + { + return SUCCESS; + } + return FAILED; + case FAILED: + default: + DBG1(DBG_TNC, "SASL %s authentication failed", + sasl->get_name(sasl)); + writer = bio_writer_create(1); + /* sending abort does not allow the client to retry */ + writer->write_uint8(writer, PT_TLS_SASL_RESULT_ABORT); + pt_tls_write(this->tls, writer, PT_TLS_SASL_RESULT, + this->identifier++); + return FAILED; + } +} + +/** + * Send the list of supported SASL mechanisms + */ +static bool send_sasl_mechs(private_pt_tls_server_t *this) +{ + enumerator_t *enumerator; + bio_writer_t *writer = NULL; + char *name; + + enumerator = sasl_mechanism_create_enumerator(TRUE); + while (enumerator->enumerate(enumerator, &name)) + { + if (!writer) + { + writer = bio_writer_create(32); + } + DBG1(DBG_TNC, "offering SASL %s", name); + writer->write_data8(writer, chunk_from_str(name)); + } + enumerator->destroy(enumerator); + + if (!writer) + { /* no mechanisms available? */ + return FALSE; + } + return pt_tls_write(this->tls, writer, PT_TLS_SASL_MECHS, + this->identifier++); +} + +/** + * Read the selected SASL mechanism, and process piggybacked data + */ +static status_t read_sasl_mech_selection(private_pt_tls_server_t *this, + sasl_mechanism_t **out) +{ + u_int32_t vendor, type, identifier; + sasl_mechanism_t *sasl; + bio_reader_t *reader; + chunk_t chunk; + u_int8_t len; + char buf[21]; + + reader = pt_tls_read(this->tls, &vendor, &type, &identifier); + if (!reader) + { + return FAILED; + } + if (vendor != 0 || type != PT_TLS_SASL_MECH_SELECTION || + !reader->read_uint8(reader, &len) || + !reader->read_data(reader, len & 0x1F, &chunk)) + { + reader->destroy(reader); + return FAILED; + } + snprintf(buf, sizeof(buf), "%.*s", (int)chunk.len, chunk.ptr); + + DBG1(DBG_TNC, "client starts SASL %s authentication", buf); + + sasl = sasl_mechanism_create(buf, NULL); + if (!sasl) + { + reader->destroy(reader); + return FAILED; + } + /* initial SASL data piggybacked? */ + if (reader->remaining(reader)) + { + switch (process_sasl(this, sasl, reader->peek(reader))) + { + case NEED_MORE: + break; + case SUCCESS: + reader->destroy(reader); + *out = sasl; + return SUCCESS; + case FAILED: + default: + reader->destroy(reader); + sasl->destroy(sasl); + return FAILED; + } + } + reader->destroy(reader); + *out = sasl; + return NEED_MORE; +} + +/** + * Do a single SASL exchange + */ +static bool do_sasl(private_pt_tls_server_t *this) +{ + sasl_mechanism_t *sasl; + status_t status; + + switch (this->auth) + { + case PT_TLS_AUTH_NONE: + return TRUE; + case PT_TLS_AUTH_TLS: + if (this->tls->get_peer_id(this->tls)) + { + return TRUE; + } + DBG1(DBG_TNC, "requiring TLS certificate client authentication"); + return FALSE; + case PT_TLS_AUTH_SASL: + break; + case PT_TLS_AUTH_TLS_OR_SASL: + if (this->tls->get_peer_id(this->tls)) + { + DBG1(DBG_TNC, "skipping SASL, client authenticated with TLS " + "certificate"); + return TRUE; + } + break; + case PT_TLS_AUTH_TLS_AND_SASL: + default: + if (!this->tls->get_peer_id(this->tls)) + { + DBG1(DBG_TNC, "requiring TLS certificate client authentication"); + return FALSE; + } + break; + } + + if (!send_sasl_mechs(this)) + { + return FALSE; + } + status = read_sasl_mech_selection(this, &sasl); + if (status == FAILED) + { + return FALSE; + } + while (status == NEED_MORE) + { + status = write_sasl(this, sasl); + if (status == NEED_MORE) + { + status = read_sasl(this, sasl); + } + } + sasl->destroy(sasl); + return status == SUCCESS; +} + +/** + * Authenticated PT-TLS session with a single SASL method + */ +static bool authenticate(private_pt_tls_server_t *this) +{ + if (do_sasl(this)) + { + /* complete SASL with emtpy mechanism list */ + bio_writer_t *writer; + + writer = bio_writer_create(0); + return pt_tls_write(this->tls, writer, PT_TLS_SASL_MECHS, + this->identifier++); + } + return FALSE; +} + +/** + * Perform assessment + */ +static bool assess(private_pt_tls_server_t *this, tls_t *tnccs) +{ + while (TRUE) + { + bio_writer_t *writer; + bio_reader_t *reader; + u_int32_t vendor, type, identifier; + chunk_t data; + + writer = bio_writer_create(32); + while (TRUE) + { + char buf[2048]; + size_t buflen, msglen; + + buflen = sizeof(buf); + switch (tnccs->build(tnccs, buf, &buflen, &msglen)) + { + case SUCCESS: + writer->destroy(writer); + return tnccs->is_complete(tnccs); + case FAILED: + default: + writer->destroy(writer); + return FALSE; + case INVALID_STATE: + writer->destroy(writer); + break; + case NEED_MORE: + writer->write_data(writer, chunk_create(buf, buflen)); + continue; + case ALREADY_DONE: + writer->write_data(writer, chunk_create(buf, buflen)); + if (!pt_tls_write(this->tls, writer, PT_TLS_PB_TNC_BATCH, + this->identifier++)) + { + return FALSE; + } + writer = bio_writer_create(32); + continue; + } + break; + } + + reader = pt_tls_read(this->tls, &vendor, &type, &identifier); + if (!reader) + { + return FALSE; + } + if (vendor == 0) + { + if (type == PT_TLS_ERROR) + { + DBG1(DBG_TNC, "received PT-TLS error"); + reader->destroy(reader); + return FALSE; + } + if (type != PT_TLS_PB_TNC_BATCH) + { + DBG1(DBG_TNC, "unexpected PT-TLS message: %d", type); + reader->destroy(reader); + return FALSE; + } + data = reader->peek(reader); + switch (tnccs->process(tnccs, data.ptr, data.len)) + { + case SUCCESS: + reader->destroy(reader); + return tnccs->is_complete(tnccs); + case FAILED: + default: + reader->destroy(reader); + return FALSE; + case NEED_MORE: + break; + } + } + else + { + DBG1(DBG_TNC, "ignoring vendor specific PT-TLS message"); + } + reader->destroy(reader); + } +} + +METHOD(pt_tls_server_t, handle, status_t, + private_pt_tls_server_t *this) +{ + switch (this->state) + { + case PT_TLS_SERVER_VERSION: + if (!negotiate_version(this)) + { + return FAILED; + } + DBG1(DBG_TNC, "negotiated PT-TLS version %d", PT_TLS_VERSION); + this->state = PT_TLS_SERVER_AUTH; + break; + case PT_TLS_SERVER_AUTH: + if (!authenticate(this)) + { + return FAILED; + } + this->state = PT_TLS_SERVER_TNCCS; + break; + case PT_TLS_SERVER_TNCCS: + if (!assess(this, (tls_t*)this->tnccs)) + { + return FAILED; + } + this->state = PT_TLS_SERVER_END; + return SUCCESS; + default: + return FAILED; + } + return NEED_MORE; +} + +METHOD(pt_tls_server_t, get_fd, int, + private_pt_tls_server_t *this) +{ + return this->tls->get_fd(this->tls); +} + +METHOD(pt_tls_server_t, destroy, void, + private_pt_tls_server_t *this) +{ + this->tnccs->destroy(this->tnccs); + this->tls->destroy(this->tls); + free(this); +} + +/** + * See header + */ +pt_tls_server_t *pt_tls_server_create(identification_t *server, int fd, + pt_tls_auth_t auth, tnccs_t *tnccs) +{ + private_pt_tls_server_t *this; + + INIT(this, + .public = { + .handle = _handle, + .get_fd = _get_fd, + .destroy = _destroy, + }, + .state = PT_TLS_SERVER_VERSION, + .tls = tls_socket_create(TRUE, server, NULL, fd, NULL), + .tnccs = (tls_t*)tnccs, + .auth = auth, + ); + + if (!this->tls) + { + this->tnccs->destroy(this->tnccs); + free(this); + return NULL; + } + + return &this->public; +} diff --git a/src/libpttls/pt_tls_server.h b/src/libpttls/pt_tls_server.h new file mode 100644 index 000000000..3e18aee8f --- /dev/null +++ b/src/libpttls/pt_tls_server.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2012 Martin Willi + * Copyright (C) 2012 revosec AG + * + * 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 pt_tls_server pt_tls_server + * @{ @ingroup pt_tls + */ + +#ifndef PT_TLS_SERVER_H_ +#define PT_TLS_SERVER_H_ + +#include <utils/identification.h> + +#include <tnc/tnccs/tnccs.h> + +#include "pt_tls.h" + +typedef struct pt_tls_server_t pt_tls_server_t; + +/** + * IF-T for TLS aka PT-TLS transport server. + */ +struct pt_tls_server_t { + + /** + * Handle assessment data read from socket. + * + * @return + * - NEED_MORE if more exchanges required, + * - SUCCESS if assessment complete + * - FAILED if assessment failed + */ + status_t (*handle)(pt_tls_server_t *this); + + /** + * Get the underlying client connection socket. + * + * @return socket fd, suitable to select() + */ + int (*get_fd)(pt_tls_server_t *this); + + /** + * Destroy a pt_tls_server_t. + */ + void (*destroy)(pt_tls_server_t *this); +}; + +/** + * Create a pt_tls_server connection instance. + * + * @param server TLS server identity + * @param fd client connection socket + * @param auth client authentication requirements + * @param tnccs inner TNCCS protocol handler to use for this connection + * @return PT-TLS server + */ +pt_tls_server_t *pt_tls_server_create(identification_t *server, int fd, + pt_tls_auth_t auth, tnccs_t *tnccs); + +#endif /** PT_TLS_SERVER_H_ @}*/ diff --git a/src/libpttls/sasl/sasl_mechanism.c b/src/libpttls/sasl/sasl_mechanism.c new file mode 100644 index 000000000..05a02e56d --- /dev/null +++ b/src/libpttls/sasl/sasl_mechanism.c @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * 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 "sasl_mechanism.h" + +#include "sasl_plain/sasl_plain.h" + +/** + * Available SASL mechanisms. + */ +static struct { + char *name; + bool server; + sasl_mechanism_constructor_t create; +} mechs[] = { + { "PLAIN", TRUE, (sasl_mechanism_constructor_t)sasl_plain_create }, + { "PLAIN", FALSE, (sasl_mechanism_constructor_t)sasl_plain_create }, +}; + +/** + * See header. + */ +sasl_mechanism_t *sasl_mechanism_create(char *name, identification_t *client) +{ + int i; + + for (i = 0; i < countof(mechs); i++) + { + if (streq(mechs[i].name, name) && mechs[i].server == (client == NULL)) + { + return mechs[i].create(name, client); + } + } + return NULL; +} + +/** + * SASL mechanism enumerator + */ +typedef struct { + /** implements enumerator_t */ + enumerator_t public; + /** looking for client or server? */ + bool server; + /** position in mechs[] */ + int i; +} mech_enumerator_t; + +METHOD(enumerator_t, mech_enumerate, bool, + mech_enumerator_t *this, char **name) +{ + while (this->i < countof(mechs)) + { + if (mechs[this->i].server == this->server) + { + *name = mechs[this->i].name; + this->i++; + return TRUE; + } + this->i++; + } + return FALSE; +} + +/** + * See header. + */ +enumerator_t* sasl_mechanism_create_enumerator(bool server) +{ + mech_enumerator_t *enumerator; + + INIT(enumerator, + .public = { + .enumerate = (void*)_mech_enumerate, + .destroy = (void*)free, + }, + .server = server, + ); + return &enumerator->public; +} diff --git a/src/libpttls/sasl/sasl_mechanism.h b/src/libpttls/sasl/sasl_mechanism.h new file mode 100644 index 000000000..1a23a119e --- /dev/null +++ b/src/libpttls/sasl/sasl_mechanism.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * 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 sasl_mechanism sasl_mechanism + * @{ @ingroup sasl + */ + +#ifndef SASL_MECHANISM_H_ +#define SASL_MECHANISM_H_ + +typedef struct sasl_mechanism_t sasl_mechanism_t; + +#include <library.h> + +/** + * Constructor function for SASL mechansims. + * + * @param name name of the requested SASL mechanism + * @param client client identity, NULL to act as server + * @return SASL mechanism, NULL on failure + */ +typedef sasl_mechanism_t*(*sasl_mechanism_constructor_t)(char *name, + identification_t *client); + +/** + * Generic interface for SASL mechanisms. + */ +struct sasl_mechanism_t { + + /** + * Get the name of this SASL mechanism. + * + * @return name of SASL mechanism + */ + char* (*get_name)(sasl_mechanism_t *this); + + /** + * Build a SASL message to send to remote host. + * + * A message is returned if the return value is NEED_MORE or SUCCESS. A + * client MUST NOT return SUCCESS in build(), as the final message + * is always from server to client (even if it is an empty result message). + * + * @param message receives allocated SASL message, to free + * @return + * - FAILED if mechanism failed + * - NEED_MORE if additional exchanges required + * - INVALID_STATE if currently nothing to build + * - SUCCESS if mechanism authenticated successfully + */ + status_t (*build)(sasl_mechanism_t *this, chunk_t *message); + + /** + * Process a SASL message received from remote host. + * + * If a server returns SUCCESS during process(), an empty result message + * is sent to complete the SASL exchange. + * + * @param message received SASL message to process + * @return + * - FAILED if mechanism failed + * - NEED_MORE if additional exchanges required + * - SUCCESS if mechanism authenticated successfully + */ + status_t (*process)(sasl_mechanism_t *this, chunk_t message); + + /** + * Destroy a sasl_mechanism_t. + */ + void (*destroy)(sasl_mechanism_t *this); +}; + +/** + * Create a sasl_mechanism instance. + * + * @param name name of SASL mechanism to create + * @param client client identity, NULL to act as server + * @return SASL mechanism instance, NULL if not found + */ +sasl_mechanism_t *sasl_mechanism_create(char *name, identification_t *client); + +/** + * Create an enumerator over supported SASL mechanism names. + * + * @param server TRUE for server instance, FALSE for client + * @return enumerator over char* + */ +enumerator_t* sasl_mechanism_create_enumerator(bool server); + +#endif /** SASL_MECHANISM_H_ @}*/ diff --git a/src/libpttls/sasl/sasl_plain/sasl_plain.c b/src/libpttls/sasl/sasl_plain/sasl_plain.c new file mode 100644 index 000000000..e8d6dc80b --- /dev/null +++ b/src/libpttls/sasl/sasl_plain/sasl_plain.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * 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 "sasl_plain.h" + +#include <utils/debug.h> + +typedef struct private_sasl_plain_t private_sasl_plain_t; + +/** + * Private data of an sasl_plain_t object. + */ +struct private_sasl_plain_t { + + /** + * Public sasl_plain_t interface. + */ + sasl_plain_t public; + + /** + * Client identity + */ + identification_t *client; +}; + +METHOD(sasl_mechanism_t, get_name, char*, + private_sasl_plain_t *this) +{ + return "PLAIN"; +} + +METHOD(sasl_mechanism_t, build_server, status_t, + private_sasl_plain_t *this, chunk_t *message) +{ + /* gets never called */ + return FAILED; +} + +METHOD(sasl_mechanism_t, process_server, status_t, + private_sasl_plain_t *this, chunk_t message) +{ + chunk_t authz, authi, password; + identification_t *id; + shared_key_t *shared; + u_char *pos; + + pos = memchr(message.ptr, 0, message.len); + if (!pos) + { + DBG1(DBG_CFG, "invalid authz encoding"); + return FAILED; + } + authz = chunk_create(message.ptr, pos - message.ptr); + message = chunk_skip(message, authz.len + 1); + pos = memchr(message.ptr, 0, message.len); + if (!pos) + { + DBG1(DBG_CFG, "invalid authi encoding"); + return FAILED; + } + authi = chunk_create(message.ptr, pos - message.ptr); + password = chunk_skip(message, authi.len + 1); + id = identification_create_from_data(authi); + shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, id, NULL); + if (!shared) + { + DBG1(DBG_CFG, "no shared secret found for '%Y'", id); + id->destroy(id); + return FAILED; + } + if (!chunk_equals(shared->get_key(shared), password)) + { + DBG1(DBG_CFG, "shared secret for '%Y' does not match", id); + id->destroy(id); + shared->destroy(shared); + return FAILED; + } + id->destroy(id); + shared->destroy(shared); + return SUCCESS; +} + +METHOD(sasl_mechanism_t, build_client, status_t, + private_sasl_plain_t *this, chunk_t *message) +{ + shared_key_t *shared; + chunk_t password; + char buf[256]; + ssize_t len; + + /* we currently use the EAP type of shared secret */ + shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, + this->client, NULL); + if (!shared) + { + DBG1(DBG_CFG, "no shared secret found for %Y", this->client); + return FAILED; + } + + password = shared->get_key(shared); + len = snprintf(buf, sizeof(buf), "%s%c%Y%c%.*s", + "", 0, this->client, 0, + (int)password.len, password.ptr); + if (len < 0 || len >= sizeof(buf)) + { + return FAILED; + } + *message = chunk_clone(chunk_create(buf, len)); + return NEED_MORE; +} + +METHOD(sasl_mechanism_t, process_client, status_t, + private_sasl_plain_t *this, chunk_t message) +{ + /* if the server sends a result, authentication successful */ + return SUCCESS; +} + +METHOD(sasl_mechanism_t, destroy, void, + private_sasl_plain_t *this) +{ + DESTROY_IF(this->client); + free(this); +} + +/** + * See header + */ +sasl_plain_t *sasl_plain_create(char *name, identification_t *client) +{ + private_sasl_plain_t *this; + + if (!streq(get_name(NULL), name)) + { + return NULL; + } + + INIT(this, + .public = { + .sasl = { + .get_name = _get_name, + .destroy = _destroy, + }, + }, + ); + + if (client) + { + this->public.sasl.build = _build_client; + this->public.sasl.process = _process_client; + this->client = client->clone(client); + } + else + { + this->public.sasl.build = _build_server; + this->public.sasl.process = _process_server; + } + return &this->public; +} diff --git a/src/libpttls/sasl/sasl_plain/sasl_plain.h b/src/libpttls/sasl/sasl_plain/sasl_plain.h new file mode 100644 index 000000000..08b7fc76f --- /dev/null +++ b/src/libpttls/sasl/sasl_plain/sasl_plain.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2013 Martin Willi + * Copyright (C) 2013 revosec AG + * + * 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 sasl_plain sasl_plain + * @{ @ingroup sasl + */ + +#ifndef SASL_PLAIN_H_ +#define SASL_PLAIN_H_ + +#include <sasl/sasl_mechanism.h> + +typedef struct sasl_plain_t sasl_plain_t; + +/** + * SASL Mechanism implementing PLAIN. + */ +struct sasl_plain_t { + + /** + * Implements sasl_mechanism_t + */ + sasl_mechanism_t sasl; +}; + +/** + * Create a sasl_plain instance. + * + * @param name name of mechanism, must be "PLAIN" + * @param client client identity, NULL to act as server + * @return mechanism implementing PLAIN, NULL on error + */ +sasl_plain_t *sasl_plain_create(char *name, identification_t *client); + +#endif /** SASL_PLAIN_H_ @}*/ diff --git a/src/libradius/radius_message.h b/src/libradius/radius_message.h index f9c57c5ef..18ec581e5 100644 --- a/src/libradius/radius_message.h +++ b/src/libradius/radius_message.h @@ -280,11 +280,6 @@ struct radius_message_t { }; /** - * Dummy libradius initialization function needed for integrity test - */ -void libradius_init(void); - -/** * Create an empty RADIUS message. * * @param code request type @@ -300,4 +295,13 @@ radius_message_t *radius_message_create(radius_message_code_t code); */ radius_message_t *radius_message_parse(chunk_t data); +/** + * @} + * @addtogroup libradius + * @{ + * + * Dummy libradius initialization function needed for integrity test + */ +void libradius_init(void); + #endif /** RADIUS_MESSAGE_H_ @}*/ diff --git a/src/libsimaka/simaka_manager.h b/src/libsimaka/simaka_manager.h index 810cb0685..bdd50296e 100644 --- a/src/libsimaka/simaka_manager.h +++ b/src/libsimaka/simaka_manager.h @@ -279,11 +279,6 @@ struct simaka_manager_t { }; /** - * Dummy libsimaka initialization function needed for integrity test - */ -void libsimaka_init(void); - -/** * Create an SIM/AKA manager to handle multiple (U)SIM cards/providers. * * @return simaka_t object @@ -312,4 +307,13 @@ typedef void* (*simaka_manager_register_cb_t)(plugin_t *plugin); bool simaka_manager_register(plugin_t *plugin, plugin_feature_t *feature, bool reg, void *data); +/** + * @} + * @addtogroup libsimaka + * @{ + * + * Dummy libsimaka initialization function needed for integrity test + */ +void libsimaka_init(void); + #endif /** SIMAKA_MANAGER_H_ @}*/ diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk index 65cfe5292..a46b0d9a1 100644 --- a/src/libstrongswan/Android.mk +++ b/src/libstrongswan/Android.mk @@ -28,6 +28,7 @@ networking/host.c networking/host_resolver.c networking/packet.c \ networking/tun_device.c \ pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c \ processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \ +resolver/resolver_manager.c resolver/rr_set.c \ selectors/traffic_selector.c threading/thread.c threading/thread_value.c \ threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \ utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \ diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index 9c4665eeb..8d6c4583a 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -26,6 +26,7 @@ networking/host.c networking/host_resolver.c networking/packet.c \ networking/tun_device.c \ pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c \ processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \ +resolver/resolver_manager.c resolver/rr_set.c \ selectors/traffic_selector.c threading/thread.c threading/thread_value.c \ threading/mutex.c threading/semaphore.c threading/rwlock.c threading/spinlock.c \ utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \ @@ -63,6 +64,8 @@ database/database.h database/database_factory.h fetcher/fetcher.h \ fetcher/fetcher_manager.h eap/eap.h pen/pen.h ipsec/ipsec_types.h \ networking/host.h networking/host_resolver.h networking/packet.h \ networking/tun_device.h \ +resolver/resolver.h resolver/resolver_response.h resolver/rr_set.h \ +resolver/rr.h resolver/resolver_manager.h \ plugins/plugin_loader.h plugins/plugin.h plugins/plugin_feature.h \ processing/jobs/job.h processing/jobs/callback_job.h processing/processor.h \ processing/scheduler.h selectors/traffic_selector.h \ @@ -323,6 +326,13 @@ if MONOLITHIC endif endif +if USE_UNBOUND + SUBDIRS += plugins/unbound +if MONOLITHIC + libstrongswan_la_LIBADD += plugins/unbound/libstrongswan-unbound.la +endif +endif + if USE_SOUP SUBDIRS += plugins/soup if MONOLITHIC diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt index c4677a537..49ef1cdf2 100644 --- a/src/libstrongswan/asn1/oid.txt +++ b/src/libstrongswan/asn1/oid.txt @@ -213,7 +213,13 @@ 0x08 "timeStamping" 0x09 "ocspSigning" OID_OCSP_SIGNING 0x08 "id-otherNames" + 0x01 "personalData" + 0x02 "userGroup" + 0x03 "id-on-permanentIdentifier" + 0x04 "id-on-hardwareModuleName" 0x05 "xmppAddr" OID_XMPP_ADDR + 0x06 "id-on-SIM" + 0x07 "id-on-dnsSRV" 0x0A "id-aca" 0x01 "authenticationInfo" OID_AUTHENTICATION_INFO 0x02 "accessIdentity" OID_ACCESS_IDENTITY diff --git a/src/libstrongswan/bio/bio_reader.c b/src/libstrongswan/bio/bio_reader.c index 17815d6c0..29b9e7279 100644 --- a/src/libstrongswan/bio/bio_reader.c +++ b/src/libstrongswan/bio/bio_reader.c @@ -36,6 +36,11 @@ struct private_bio_reader_t { * Remaining data to process */ chunk_t buf; + + /** + * Optional data to free during destruction + */ + chunk_t cleanup; }; METHOD(bio_reader_t, remaining, u_int32_t, @@ -302,6 +307,7 @@ METHOD(bio_reader_t, read_data32, bool, METHOD(bio_reader_t, destroy, void, private_bio_reader_t *this) { + free(this->cleanup.ptr); free(this); } @@ -339,3 +345,17 @@ bio_reader_t *bio_reader_create(chunk_t data) return &this->public; } + +/** + * See header + */ +bio_reader_t *bio_reader_create_own(chunk_t data) +{ + private_bio_reader_t *this; + + this = (private_bio_reader_t*)bio_reader_create(data); + + this->cleanup = data; + + return &this->public; +} diff --git a/src/libstrongswan/bio/bio_reader.h b/src/libstrongswan/bio/bio_reader.h index 3162f3eda..475422428 100644 --- a/src/libstrongswan/bio/bio_reader.h +++ b/src/libstrongswan/bio/bio_reader.h @@ -187,7 +187,18 @@ struct bio_reader_t { /** * Create a bio_reader instance. + * + * @param data data buffer, must survive lifetime of reader + * @return reader */ bio_reader_t *bio_reader_create(chunk_t data); -#endif /** bio_reader_H_ @}*/ +/** + * Create a bio_reader instance owning buffer. + * + * @param data data buffer, gets freed with destroy() + * @return reader + */ +bio_reader_t *bio_reader_create_own(chunk_t data); + +#endif /** BIO_READER_H_ @}*/ diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c index a718de3dc..d2d0a7d72 100644 --- a/src/libstrongswan/credentials/auth_cfg.c +++ b/src/libstrongswan/credentials/auth_cfg.c @@ -76,7 +76,6 @@ static inline bool is_multi_value_rule(auth_rule_t type) case AUTH_RULE_AAA_IDENTITY: case AUTH_RULE_XAUTH_IDENTITY: case AUTH_RULE_XAUTH_BACKEND: - case AUTH_RULE_SUBJECT_CERT: case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_SUBJECT_HASH_URL: case AUTH_RULE_MAX: @@ -84,6 +83,7 @@ static inline bool is_multi_value_rule(auth_rule_t type) case AUTH_RULE_OCSP_VALIDATION: case AUTH_RULE_CRL_VALIDATION: case AUTH_RULE_GROUP: + case AUTH_RULE_SUBJECT_CERT: case AUTH_RULE_CA_CERT: case AUTH_RULE_IM_CERT: case AUTH_RULE_CERT_POLICY: @@ -503,8 +503,9 @@ METHOD(auth_cfg_t, complies, bool, private_auth_cfg_t *this, auth_cfg_t *constraints, bool log_error) { enumerator_t *e1, *e2; - bool success = TRUE, group_match = FALSE; + bool success = TRUE, group_match = FALSE, cert_match = FALSE; identification_t *require_group = NULL; + certificate_t *require_cert = NULL; signature_scheme_t scheme = SIGN_UNKNOWN; u_int strength = 0; auth_rule_t t1, t2; @@ -542,20 +543,21 @@ METHOD(auth_cfg_t, complies, bool, } case AUTH_RULE_SUBJECT_CERT: { - certificate_t *c1, *c2; + certificate_t *cert; - c1 = (certificate_t*)value; - c2 = get(this, AUTH_RULE_SUBJECT_CERT); - if (!c2 || !c1->equals(c1, c2)) + /* for certs, a match of a single cert is sufficient */ + require_cert = (certificate_t*)value; + + e2 = create_enumerator(this); + while (e2->enumerate(e2, &t2, &cert)) { - success = FALSE; - if (log_error) + if (t2 == AUTH_RULE_SUBJECT_CERT && + cert->equals(cert, require_cert)) { - DBG1(DBG_CFG, "constraint check failed: peer not " - "authenticated with peer cert '%Y'.", - c1->get_subject(c1)); + cert_match = TRUE; } } + e2->destroy(e2); break; } case AUTH_RULE_CRL_VALIDATION: @@ -828,6 +830,17 @@ METHOD(auth_cfg_t, complies, bool, } return FALSE; } + + if (require_cert && !cert_match) + { + if (log_error) + { + DBG1(DBG_CFG, "constraint check failed: peer not " + "authenticated with peer cert '%Y'.", + require_cert->get_subject(require_cert)); + } + return FALSE; + } return success; } @@ -999,14 +1012,15 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, { enumerator_t *enumerator; auth_cfg_t *clone; - entry_t *entry; + auth_rule_t type; + void *value; clone = auth_cfg_create(); /* this enumerator skips duplicates for rules we expect only once */ - enumerator = this->entries->create_enumerator(this->entries); - while (enumerator->enumerate(enumerator, &entry)) + enumerator = create_enumerator(this); + while (enumerator->enumerate(enumerator, &type, &value)) { - switch (entry->type) + switch (type) { case AUTH_RULE_IDENTITY: case AUTH_RULE_EAP_IDENTITY: @@ -1014,8 +1028,8 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, case AUTH_RULE_GROUP: case AUTH_RULE_XAUTH_IDENTITY: { - identification_t *id = (identification_t*)entry->value; - clone->add(clone, entry->type, id->clone(id)); + identification_t *id = (identification_t*)value; + clone->add(clone, type, id->clone(id)); break; } case AUTH_RULE_CA_CERT: @@ -1025,8 +1039,8 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, case AUTH_HELPER_SUBJECT_CERT: case AUTH_HELPER_REVOCATION_CERT: { - certificate_t *cert = (certificate_t*)entry->value; - clone->add(clone, entry->type, cert->get_ref(cert)); + certificate_t *cert = (certificate_t*)value; + clone->add(clone, type, cert->get_ref(cert)); break; } case AUTH_RULE_XAUTH_BACKEND: @@ -1034,7 +1048,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, case AUTH_HELPER_IM_HASH_URL: case AUTH_HELPER_SUBJECT_HASH_URL: { - clone->add(clone, entry->type, strdup(entry->value)); + clone->add(clone, type, strdup(value)); break; } case AUTH_RULE_IDENTITY_LOOSE: @@ -1046,7 +1060,7 @@ METHOD(auth_cfg_t, clone_, auth_cfg_t*, case AUTH_RULE_RSA_STRENGTH: case AUTH_RULE_ECDSA_STRENGTH: case AUTH_RULE_SIGNATURE_SCHEME: - clone->add(clone, entry->type, (uintptr_t)entry->value); + clone->add(clone, type, (uintptr_t)value); break; case AUTH_RULE_MAX: break; diff --git a/src/libstrongswan/credentials/cert_validator.h b/src/libstrongswan/credentials/cert_validator.h index 00e30d7a0..325fa0af3 100644 --- a/src/libstrongswan/credentials/cert_validator.h +++ b/src/libstrongswan/credentials/cert_validator.h @@ -35,6 +35,22 @@ typedef struct cert_validator_t cert_validator_t; struct cert_validator_t { /** + * Check the lifetime of a certificate. + * + * If this function returns SUCCESS or FAILED, the certificate lifetime is + * considered definitely (in-)valid, without asking other validators. + * If all registered validaters return NEED_MORE, the default + * lifetime check is performed. + * + * @param cert certificate to check lifetime + * @param pathlen the current length of the path bottom-up + * @param anchor is certificate trusted root anchor? + * @param auth container for resulting authentication info + * @return SUCCESS, FAILED or NEED_MORE to ask next validator + */ + status_t (*check_lifetime)(cert_validator_t *this, certificate_t *cert, + int pathlen, bool anchor, auth_cfg_t *auth); + /** * Validate a subject certificate in relation to its issuer. * * @param subject subject certificate to check @@ -43,6 +59,7 @@ struct cert_validator_t { * @param pathlen the current length of the path bottom-up * @param anchor is issuer trusted root anchor * @param auth container for resulting authentication info + * @return TRUE if subject certificate valid */ bool (*validate)(cert_validator_t *this, certificate_t *subject, certificate_t *issuer, bool online, u_int pathlen, diff --git a/src/libstrongswan/credentials/cred_encoding.h b/src/libstrongswan/credentials/cred_encoding.h index b029fe2ac..41481f376 100644 --- a/src/libstrongswan/credentials/cred_encoding.h +++ b/src/libstrongswan/credentials/cred_encoding.h @@ -85,6 +85,8 @@ enum cred_encoding_type_t { /** PGP key encoding */ PUBKEY_PGP, PRIVKEY_PGP, + /** DNSKEY encoding */ + PUBKEY_DNSKEY, /** ASN.1 DER encoded certificate */ CERT_ASN1_DER, diff --git a/src/libstrongswan/credentials/credential_manager.c b/src/libstrongswan/credentials/credential_manager.c index 9e40c5a10..f4cd9b9e6 100644 --- a/src/libstrongswan/credentials/credential_manager.c +++ b/src/libstrongswan/credentials/credential_manager.c @@ -515,32 +515,74 @@ static void cache_queue(private_credential_manager_t *this) } /** + * Use validators to check the lifetime of certificates + */ +static bool check_lifetime(private_credential_manager_t *this, + certificate_t *cert, char *label, + int pathlen, bool trusted, auth_cfg_t *auth) +{ + time_t not_before, not_after; + cert_validator_t *validator; + enumerator_t *enumerator; + status_t status = NEED_MORE; + + enumerator = this->validators->create_enumerator(this->validators); + while (enumerator->enumerate(enumerator, &validator)) + { + if (!validator->check_lifetime) + { + continue; + } + status = validator->check_lifetime(validator, cert, + pathlen, trusted, auth); + if (status != NEED_MORE) + { + break; + } + } + enumerator->destroy(enumerator); + + switch (status) + { + case NEED_MORE: + if (!cert->get_validity(cert, NULL, ¬_before, ¬_after)) + { + DBG1(DBG_CFG, "%s certificate invalid (valid from %T to %T)", + label, ¬_before, FALSE, ¬_after, FALSE); + return FALSE; + } + return TRUE; + case SUCCESS: + return TRUE; + case FAILED: + default: + return FALSE; + } +} + +/** * check a certificate for its lifetime */ static bool check_certificate(private_credential_manager_t *this, certificate_t *subject, certificate_t *issuer, bool online, int pathlen, bool trusted, auth_cfg_t *auth) { - time_t not_before, not_after; cert_validator_t *validator; enumerator_t *enumerator; - if (!subject->get_validity(subject, NULL, ¬_before, ¬_after)) + if (!check_lifetime(this, subject, "subject", pathlen, FALSE, auth) || + !check_lifetime(this, issuer, "issuer", pathlen + 1, trusted, auth)) { - DBG1(DBG_CFG, "subject certificate invalid (valid from %T to %T)", - ¬_before, FALSE, ¬_after, FALSE); - return FALSE; - } - if (!issuer->get_validity(issuer, NULL, ¬_before, ¬_after)) - { - DBG1(DBG_CFG, "issuer certificate invalid (valid from %T to %T)", - ¬_before, FALSE, ¬_after, FALSE); return FALSE; } enumerator = this->validators->create_enumerator(this->validators); while (enumerator->enumerate(enumerator, &validator)) { + if (!validator->validate) + { + continue; + } if (!validator->validate(validator, subject, issuer, online, pathlen, trusted, auth)) { @@ -1041,6 +1083,29 @@ static private_key_t *get_private_by_cert(private_credential_manager_t *this, return private; } +/** + * Move the actually used certificate to front, so it gets returned with get() + */ +static void prefer_cert(auth_cfg_t *auth, certificate_t *cert) +{ + enumerator_t *enumerator; + auth_rule_t rule; + certificate_t *current; + + enumerator = auth->create_enumerator(auth); + while (enumerator->enumerate(enumerator, &rule, ¤t)) + { + if (rule == AUTH_RULE_SUBJECT_CERT) + { + current->get_ref(current); + auth->replace(auth, enumerator, AUTH_RULE_SUBJECT_CERT, cert); + cert = current; + } + } + enumerator->destroy(enumerator); + auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert); +} + METHOD(credential_manager_t, get_private, private_key_t*, private_credential_manager_t *this, key_type_t type, identification_t *id, auth_cfg_t *auth) @@ -1049,6 +1114,7 @@ METHOD(credential_manager_t, get_private, private_key_t*, certificate_t *cert; private_key_t *private = NULL; auth_cfg_t *trustchain; + auth_rule_t rule; /* check if this is a lookup by key ID, and do it if so */ if (id && id->get_type(id) == ID_KEY_ID) @@ -1062,7 +1128,35 @@ METHOD(credential_manager_t, get_private, private_key_t*, if (auth) { - /* if a specific certificate is preferred, check for a matching key */ + /* try to find a trustchain with one of the configured subject certs */ + enumerator = auth->create_enumerator(auth); + while (enumerator->enumerate(enumerator, &rule, &cert)) + { + if (rule == AUTH_RULE_SUBJECT_CERT) + { + private = get_private_by_cert(this, cert, type); + if (private) + { + trustchain = build_trustchain(this, cert, auth); + if (trustchain) + { + auth->merge(auth, trustchain, FALSE); + prefer_cert(auth, cert->get_ref(cert)); + trustchain->destroy(trustchain); + break; + } + private->destroy(private); + private = NULL; + } + } + } + enumerator->destroy(enumerator); + if (private) + { + return private; + } + + /* if none yielded a trustchain, enforce the first configured cert */ cert = auth->get(auth, AUTH_RULE_SUBJECT_CERT); if (cert) { diff --git a/src/libstrongswan/crypto/crypto_tester.c b/src/libstrongswan/crypto/crypto_tester.c index 08b226468..12db0961b 100644 --- a/src/libstrongswan/crypto/crypto_tester.c +++ b/src/libstrongswan/crypto/crypto_tester.c @@ -451,7 +451,10 @@ METHOD(crypto_tester_t, test_aead, bool, failure: aead->destroy(aead); chunk_free(&cipher); - chunk_free(&plain); + if (plain.ptr != vector->plain) + { + chunk_free(&plain); + } if (failed) { DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed", diff --git a/src/libstrongswan/library.c b/src/libstrongswan/library.c index 30a7774df..819c6808e 100644 --- a/src/libstrongswan/library.c +++ b/src/libstrongswan/library.c @@ -91,6 +91,7 @@ void library_deinit() this->public.crypto->destroy(this->public.crypto); this->public.proposal->destroy(this->public.proposal); this->public.fetcher->destroy(this->public.fetcher); + this->public.resolver->destroy(this->public.resolver); this->public.db->destroy(this->public.db); this->public.printf_hook->destroy(this->public.printf_hook); this->objects->destroy(this->objects); @@ -214,6 +215,7 @@ bool library_init(char *settings) this->public.credmgr = credential_manager_create(); this->public.encoding = cred_encoding_create(); this->public.fetcher = fetcher_manager_create(); + this->public.resolver = resolver_manager_create(); this->public.db = database_factory_create(); this->public.processor = processor_create(); this->public.scheduler = scheduler_create(); diff --git a/src/libstrongswan/library.h b/src/libstrongswan/library.h index f164a6052..3b6d02002 100644 --- a/src/libstrongswan/library.h +++ b/src/libstrongswan/library.h @@ -49,6 +49,9 @@ * @defgroup fetcher fetcher * @ingroup libstrongswan * + * @defgroup resolver resolver + * @ingroup libstrongswan + * * @defgroup ipsec ipsec * @ingroup libstrongswan * @@ -92,6 +95,7 @@ #include "crypto/crypto_factory.h" #include "crypto/proposal/proposal_keywords.h" #include "fetcher/fetcher_manager.h" +#include "resolver/resolver_manager.h" #include "database/database_factory.h" #include "credentials/credential_factory.h" #include "credentials/credential_manager.h" @@ -162,6 +166,11 @@ struct library_t { fetcher_manager_t *fetcher; /** + * Manager for DNS resolvers + */ + resolver_manager_t *resolver; + + /** * database construction factory */ database_factory_t *db; diff --git a/src/libstrongswan/networking/packet.c b/src/libstrongswan/networking/packet.c index a2c329d60..4ff7fc48b 100644 --- a/src/libstrongswan/networking/packet.c +++ b/src/libstrongswan/networking/packet.c @@ -39,6 +39,11 @@ struct private_packet_t { */ host_t *destination; + /** + * DSCP value on packet + */ + u_int8_t dscp; + /** * message data */ @@ -89,6 +94,17 @@ METHOD(packet_t, set_data, void, this->adjusted_data = this->data = data; } +METHOD(packet_t, get_dscp, u_int8_t, + private_packet_t *this) +{ + return this->dscp; +} +METHOD(packet_t, set_dscp, void, + private_packet_t *this, u_int8_t value) +{ + this->dscp = value; +} + METHOD(packet_t, skip_bytes, void, private_packet_t *this, size_t bytes) { @@ -123,6 +139,7 @@ METHOD(packet_t, clone_, packet_t*, { other->set_data(other, chunk_clone(this->adjusted_data)); } + other->set_dscp(other, this->dscp); return other; } @@ -141,6 +158,8 @@ packet_t *packet_create_from_data(host_t *src, host_t *dst, chunk_t data) .get_source = _get_source, .set_destination = _set_destination, .get_destination = _get_destination, + .get_dscp = _get_dscp, + .set_dscp = _set_dscp, .skip_bytes = _skip_bytes, .clone = _clone_, .destroy = _destroy, diff --git a/src/libstrongswan/networking/packet.h b/src/libstrongswan/networking/packet.h index 6fb9cece2..a96a4b84f 100644 --- a/src/libstrongswan/networking/packet.h +++ b/src/libstrongswan/networking/packet.h @@ -76,6 +76,20 @@ struct packet_t { void (*set_data)(packet_t *packet, chunk_t data); /** + * Get the DiffServ Code Point set on this packet. + * + * @return DSCP value + */ + u_int8_t (*get_dscp)(packet_t *this); + + /** + * Set the DiffServ Code Point to use on this packet. + * + * @param value DSCP value + */ + void (*set_dscp)(packet_t *this, u_int8_t value); + + /** * Increase the offset where the actual packet data starts. * * The total offset applies to future calls of get_data() and clone(). diff --git a/src/libstrongswan/networking/tun_device.c b/src/libstrongswan/networking/tun_device.c index d07327e5c..1da87df05 100644 --- a/src/libstrongswan/networking/tun_device.c +++ b/src/libstrongswan/networking/tun_device.c @@ -88,7 +88,6 @@ static void set_netmask(struct ifreq *ifr, int family, u_int8_t netmask) case AF_INET: { struct sockaddr_in *addr = (struct sockaddr_in*)&ifr->ifr_addr; - addr->sin_family = AF_INET; target = (char*)&addr->sin_addr; len = 4; break; @@ -96,7 +95,6 @@ static void set_netmask(struct ifreq *ifr, int family, u_int8_t netmask) case AF_INET6: { struct sockaddr_in6 *addr = (struct sockaddr_in6*)&ifr->ifr_addr; - addr->sin6_family = AF_INET6; target = (char*)&addr->sin6_addr; len = 16; break; @@ -105,6 +103,8 @@ static void set_netmask(struct ifreq *ifr, int family, u_int8_t netmask) return; } + ifr->ifr_addr.sa_family = family; + bytes = (netmask + 7) / 8; bits = (bytes * 8) - netmask; diff --git a/src/libstrongswan/pen/pen.c b/src/libstrongswan/pen/pen.c index b1b0731d4..f6997d1d1 100644 --- a/src/libstrongswan/pen/pen.c +++ b/src/libstrongswan/pen/pen.c @@ -22,7 +22,7 @@ ENUM_NEXT(pen_names, PEN_IBM, PEN_IBM, PEN_IETF, ENUM_NEXT(pen_names, PEN_MICROSOFT, PEN_MICROSOFT, PEN_IBM, "Microsoft"); ENUM_NEXT(pen_names, PEN_REDHAT, PEN_REDHAT, PEN_MICROSOFT, - "Redhat"); + "Redhat"); ENUM_NEXT(pen_names, PEN_OSC, PEN_OSC, PEN_REDHAT, "OSC"); ENUM_NEXT(pen_names, PEN_DEBIAN, PEN_DEBIAN, PEN_OSC, @@ -32,7 +32,7 @@ ENUM_NEXT(pen_names, PEN_GOOGLE, PEN_GOOGLE, PEN_DEBIAN, ENUM_NEXT(pen_names, PEN_TCG, PEN_TCG, PEN_GOOGLE, "TCG"); ENUM_NEXT(pen_names, PEN_CANONICAL, PEN_CANONICAL, PEN_TCG, - "Canonical"); + "Canonical"); ENUM_NEXT(pen_names, PEN_FEDORA, PEN_FEDORA, PEN_CANONICAL, "Fedora Project"); ENUM_NEXT(pen_names, PEN_FHH, PEN_FHH, PEN_FEDORA, @@ -41,7 +41,7 @@ ENUM_NEXT(pen_names, PEN_ITA, PEN_ITA, PEN_FHH, "ITA-HSR"); ENUM_NEXT(pen_names, PEN_OPENPTS, PEN_OPENPTS, PEN_ITA, "OpenPTS"); -ENUM_NEXT(pen_names, PEN_RESERVED, PEN_RESERVED, PEN_OPENPTS, +ENUM_NEXT(pen_names, PEN_UNASSIGNED, PEN_RESERVED, PEN_OPENPTS, + "Unassigned", "Reserved"); ENUM_END(pen_names, PEN_RESERVED); - diff --git a/src/libstrongswan/pen/pen.h b/src/libstrongswan/pen/pen.h index 9d5df7d49..29e312c61 100644 --- a/src/libstrongswan/pen/pen.h +++ b/src/libstrongswan/pen/pen.h @@ -29,25 +29,31 @@ typedef enum pen_t pen_t; typedef struct pen_type_t pen_type_t; +/** + * Private enterprise numbers allocated by IANA. + * + * http://www.iana.org/assignments/enterprise-numbers + */ enum pen_t { - PEN_IETF = 0x000000, /* 0 */ - PEN_IBM = 0x000002, /* 2 */ - PEN_MICROSOFT = 0x000137, /* 311 */ - PEN_REDHAT = 0x000908, /* 2312 */ - PEN_OSC = 0x002358, /* 9048 */ - PEN_DEBIAN = 0x002572, /* 9586 */ - PEN_GOOGLE = 0x002B79, /* 11129 */ - PEN_TCG = 0x005597, /* 21911 */ - PEN_CANONICAL = 0x007132, /* 28978 */ - PEN_FEDORA = 0x0076C1, /* 30401 */ - PEN_FHH = 0x0080ab, /* 32939 */ - PEN_ITA = 0x00902a, /* 36906 */ - PEN_OPENPTS = 0x00950e, /* 38158 */ - PEN_RESERVED = 0xffffff, /* 16777215 */ + PEN_IETF = 0x000000, /* 0 */ + PEN_IBM = 0x000002, /* 2 */ + PEN_MICROSOFT = 0x000137, /* 311 */ + PEN_REDHAT = 0x000908, /* 2312 */ + PEN_OSC = 0x002358, /* 9048 */ + PEN_DEBIAN = 0x002572, /* 9586 */ + PEN_GOOGLE = 0x002B79, /* 11129 */ + PEN_TCG = 0x005597, /* 21911 */ + PEN_CANONICAL = 0x007132, /* 28978 */ + PEN_FEDORA = 0x0076C1, /* 30401 */ + PEN_FHH = 0x0080ab, /* 32939 */ + PEN_ITA = 0x00902a, /* 36906 */ + PEN_OPENPTS = 0x00950e, /* 38158 */ + PEN_UNASSIGNED = 0xfffffe, /* 16777214 */ + PEN_RESERVED = 0xffffff, /* 16777215 */ }; /** - * Vendor specific type + * Vendor specific type in vendor specific namespace. */ struct pen_type_t { pen_t vendor_id; @@ -56,14 +62,44 @@ struct pen_type_t { /** * Create a pen_type_t struct + * + * @param vendor_id vendor ID to create a pen_type_t + * @param type type to create a pen_type_t + * @return created pen_type_t */ static inline pen_type_t pen_type_create(pen_t vendor_id, u_int32_t type) { - pen_type_t pen_type = {vendor_id, type}; + pen_type_t pen_type = { vendor_id, type }; return pen_type; } /** + * Check two pen_type_t for equality. + * + * @param a first pen_type_t to compare + * @param b second pen_type_t to compare + * @return TRUE if a == b + */ +static inline bool pen_type_equals(pen_type_t a, pen_type_t b) +{ + return a.vendor_id == b.vendor_id && a.type == b.type; +} + +/** + * Check if a pen_type_t matches vendor and type. + * + * @param pen_type pen_type_t to compare + * @param vendor_id vendor to check in pen_type + * @param type type to check in pen_type + * @return TRUE if vendor_id and type matches pen_type + */ +static inline bool pen_type_is(pen_type_t pen_type, + pen_t vendor_id, u_int32_t type) +{ + return pen_type.vendor_id == vendor_id && pen_type.type == type; +} + +/** * enum names for pen_t. */ extern enum_name_t *pen_names; diff --git a/src/libstrongswan/plugins/ccm/ccm_aead.h b/src/libstrongswan/plugins/ccm/ccm_aead.h index d5e302f94..79ab31804 100644 --- a/src/libstrongswan/plugins/ccm/ccm_aead.h +++ b/src/libstrongswan/plugins/ccm/ccm_aead.h @@ -42,8 +42,8 @@ struct ccm_aead_t { /** * Create a ccm_aead instance. * - * @param key_size key size in bytes * @param algo algorithm to implement, a CCM mode + * @param key_size key size in bytes * @return aead, NULL if not supported */ ccm_aead_t *ccm_aead_create(encryption_algorithm_t algo, size_t key_size); diff --git a/src/libstrongswan/plugins/curl/curl_fetcher.c b/src/libstrongswan/plugins/curl/curl_fetcher.c index c68b74f96..b49961a90 100644 --- a/src/libstrongswan/plugins/curl/curl_fetcher.c +++ b/src/libstrongswan/plugins/curl/curl_fetcher.c @@ -21,7 +21,7 @@ #include "curl_fetcher.h" -#define DEFAULT_TIMEOUT 10 +#define CONNECT_TIMEOUT 10 typedef struct private_curl_fetcher_t private_curl_fetcher_t; @@ -48,6 +48,11 @@ struct private_curl_fetcher_t { * Callback function */ fetcher_callback_t cb; + + /** + * Timeout for a transfer + */ + long timeout; }; /** @@ -94,7 +99,11 @@ METHOD(fetcher_t, fetch, status_t, curl_easy_setopt(this->curl, CURLOPT_ERRORBUFFER, error); curl_easy_setopt(this->curl, CURLOPT_FAILONERROR, TRUE); curl_easy_setopt(this->curl, CURLOPT_NOSIGNAL, TRUE); - curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, DEFAULT_TIMEOUT); + if (this->timeout) + { + curl_easy_setopt(this->curl, CURLOPT_TIMEOUT, this->timeout); + } + curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, CONNECT_TIMEOUT); curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, (void*)curl_cb); curl_easy_setopt(this->curl, CURLOPT_WRITEDATA, &data); if (this->headers) @@ -160,8 +169,7 @@ METHOD(fetcher_t, set_option, bool, } case FETCH_TIMEOUT: { - curl_easy_setopt(this->curl, CURLOPT_CONNECTTIMEOUT, - va_arg(args, u_int)); + this->timeout = va_arg(args, u_int); break; } case FETCH_CALLBACK: @@ -211,4 +219,3 @@ curl_fetcher_t *curl_fetcher_create() } return &this->public; } - diff --git a/src/libstrongswan/plugins/dnskey/Makefile.am b/src/libstrongswan/plugins/dnskey/Makefile.am index fbba95e0a..0f2e554c1 100644 --- a/src/libstrongswan/plugins/dnskey/Makefile.am +++ b/src/libstrongswan/plugins/dnskey/Makefile.am @@ -11,6 +11,7 @@ endif libstrongswan_dnskey_la_SOURCES = \ dnskey_plugin.h dnskey_plugin.c \ - dnskey_builder.h dnskey_builder.c + dnskey_builder.h dnskey_builder.c \ + dnskey_encoder.h dnskey_encoder.c libstrongswan_dnskey_la_LDFLAGS = -module -avoid-version diff --git a/src/libstrongswan/plugins/dnskey/dnskey_builder.c b/src/libstrongswan/plugins/dnskey/dnskey_builder.c index b8a451500..71040437d 100644 --- a/src/libstrongswan/plugins/dnskey/dnskey_builder.c +++ b/src/libstrongswan/plugins/dnskey/dnskey_builder.c @@ -39,8 +39,14 @@ enum dnskey_algorithm_t { DNSKEY_ALG_RSA_MD5 = 1, DNSKEY_ALG_DH = 2, DNSKEY_ALG_DSA = 3, - DNSKEY_ALG_ECC = 4, DNSKEY_ALG_RSA_SHA1 = 5, + DNSKEY_ALG_DSA_NSEC3_SHA1 = 6, + DNSKEY_ALG_RSA_SHA1_NSEC3_SHA1 = 7, + DNSKEY_ALG_RSA_SHA256 = 8, + DNSKEY_ALG_RSA_SHA512 = 10, + DNSKEY_ALG_ECC_GOST = 12, + DNSKEY_ALG_ECDSA_P256_SHA256 = 13, + DNSKEY_ALG_ECDSA_P384_SHA384 = 14 }; /** @@ -59,7 +65,11 @@ static dnskey_public_key_t *parse_public_key(chunk_t blob) switch (rr->algorithm) { + case DNSKEY_ALG_RSA_MD5: case DNSKEY_ALG_RSA_SHA1: + case DNSKEY_ALG_RSA_SHA1_NSEC3_SHA1: + case DNSKEY_ALG_RSA_SHA256: + case DNSKEY_ALG_RSA_SHA512: return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, BUILD_BLOB_DNSKEY, blob, BUILD_END); default: diff --git a/src/libstrongswan/plugins/dnskey/dnskey_encoder.c b/src/libstrongswan/plugins/dnskey/dnskey_encoder.c new file mode 100644 index 000000000..d2b9894b8 --- /dev/null +++ b/src/libstrongswan/plugins/dnskey/dnskey_encoder.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2013 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 "dnskey_encoder.h" + +#include <utils/debug.h> + +/** + * Encode an RSA public key in DNSKEY format (RFC 3110) + */ +bool build_pub(chunk_t *encoding, va_list args) +{ + chunk_t n, e, pubkey; + size_t exp_len; + u_char *pos; + + if (cred_encoding_args(args, CRED_PART_RSA_MODULUS, &n, + CRED_PART_RSA_PUB_EXP, &e, CRED_PART_END)) + { + /* remove leading zeros in exponent and modulus */ + while (*e.ptr == 0) + { + e = chunk_skip(e, 1); + } + while (*n.ptr == 0) + { + n = chunk_skip(n, 1); + } + + if (e.len < 256) + { + /* exponent length fits into a single octet */ + exp_len = 1; + pubkey = chunk_alloc(exp_len + e.len + n.len); + pubkey.ptr[0] = (char)e.len; + } + else if (e.len < 65536) + { + /* exponent length fits into two octets preceded by zero octet */ + exp_len = 3; + pubkey = chunk_alloc(exp_len + e.len + n.len); + pubkey.ptr[0] = 0x00; + htoun16(pubkey.ptr + 1, e.len); + } + else + { + /* exponent length is too large */ + return FALSE; + } + + /* copy exponent and modulus and convert to base64 format */ + pos = pubkey.ptr + exp_len; + memcpy(pos, e.ptr, e.len); + pos += e.len; + memcpy(pos, n.ptr, n.len); + *encoding = chunk_to_base64(pubkey, NULL); + chunk_free(&pubkey); + + return TRUE; + } + return FALSE; +} + +/** + * See header. + */ +bool dnskey_encoder_encode(cred_encoding_type_t type, chunk_t *encoding, + va_list args) +{ + switch (type) + { + case PUBKEY_DNSKEY: + return build_pub(encoding, args); + default: + return FALSE; + } +} + + diff --git a/src/libstrongswan/plugins/dnskey/dnskey_encoder.h b/src/libstrongswan/plugins/dnskey/dnskey_encoder.h new file mode 100644 index 000000000..127260308 --- /dev/null +++ b/src/libstrongswan/plugins/dnskey/dnskey_encoder.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2013 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 dnskey_encoder dnskey_encoder + * @{ @ingroup dnskey_p + */ + +#ifndef DNSKEY_ENCODER_H_ +#define DNSKEY_ENCODER_H_ + +#include <credentials/cred_encoding.h> + +/** + * Encoding function for DNSKEY (RFC 3110) public key format. + */ +bool dnskey_encoder_encode(cred_encoding_type_t type, chunk_t *encoding, + va_list args); + +#endif /** DNSKEY_ENCODER_H_ @}*/ diff --git a/src/libstrongswan/plugins/dnskey/dnskey_plugin.c b/src/libstrongswan/plugins/dnskey/dnskey_plugin.c index b6863e8e3..9a4f6252f 100644 --- a/src/libstrongswan/plugins/dnskey/dnskey_plugin.c +++ b/src/libstrongswan/plugins/dnskey/dnskey_plugin.c @@ -17,6 +17,7 @@ #include <library.h> #include "dnskey_builder.h" +#include "dnskey_encoder.h" typedef struct private_dnskey_plugin_t private_dnskey_plugin_t; @@ -53,6 +54,8 @@ METHOD(plugin_t, get_features, int, METHOD(plugin_t, destroy, void, private_dnskey_plugin_t *this) { + lib->encoding->remove_encoder(lib->encoding, dnskey_encoder_encode); + free(this); } @@ -73,6 +76,8 @@ plugin_t *dnskey_plugin_create() }, ); + lib->encoding->add_encoder(lib->encoding, dnskey_encoder_encode); + return &this->public.plugin; } diff --git a/src/libstrongswan/plugins/gcm/gcm_aead.h b/src/libstrongswan/plugins/gcm/gcm_aead.h index db4be2442..846c3c76c 100644 --- a/src/libstrongswan/plugins/gcm/gcm_aead.h +++ b/src/libstrongswan/plugins/gcm/gcm_aead.h @@ -42,8 +42,8 @@ struct gcm_aead_t { /** * Create a gcm_aead instance. * - * @param key_size key size in bytes * @param algo algorithm to implement, a gcm mode + * @param key_size key size in bytes * @return aead, NULL if not supported */ gcm_aead_t *gcm_aead_create(encryption_algorithm_t algo, size_t key_size); diff --git a/src/libstrongswan/plugins/openssl/Makefile.am b/src/libstrongswan/plugins/openssl/Makefile.am index f971a5e08..e71567311 100644 --- a/src/libstrongswan/plugins/openssl/Makefile.am +++ b/src/libstrongswan/plugins/openssl/Makefile.am @@ -25,7 +25,8 @@ libstrongswan_openssl_la_SOURCES = \ openssl_crl.c openssl_crl.h \ openssl_pkcs7.c openssl_pkcs7.h \ openssl_rng.c openssl_rng.h \ - openssl_hmac.c openssl_hmac.h + openssl_hmac.c openssl_hmac.h \ + openssl_gcm.c openssl_gcm.h libstrongswan_openssl_la_LDFLAGS = -module -avoid-version libstrongswan_openssl_la_LIBADD = -lcrypto diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c index 4dc5663f1..ff3382473 100644 --- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c +++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c @@ -14,6 +14,10 @@ * for more details. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_DH + #include <openssl/dh.h> #include "openssl_diffie_hellman.h" @@ -193,3 +197,5 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create( return &this->public; } + +#endif /* OPENSSL_NO_DH */ diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c index d350d050b..12f264267 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c @@ -16,7 +16,7 @@ #include <openssl/opensslconf.h> -#ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_ECDSA #include "openssl_ec_private_key.h" #include "openssl_ec_public_key.h" @@ -423,5 +423,4 @@ error: destroy(this); return NULL; } -#endif /* OPENSSL_NO_EC */ - +#endif /* OPENSSL_NO_ECDSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c index 3f5125b31..c8a45f79a 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c @@ -16,7 +16,7 @@ #include <openssl/opensslconf.h> -#ifndef OPENSSL_NO_EC +#ifndef OPENSSL_NO_ECDSA #include "openssl_ec_public_key.h" #include "openssl_util.h" @@ -360,5 +360,5 @@ openssl_ec_public_key_t *openssl_ec_public_key_load(key_type_t type, } return &this->public; } -#endif /* OPENSSL_NO_EC */ +#endif /* OPENSSL_NO_ECDSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_gcm.c b/src/libstrongswan/plugins/openssl/openssl_gcm.c new file mode 100644 index 000000000..89d1cd589 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_gcm.c @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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 <openssl/opensslv.h> + +#if OPENSSL_VERSION_NUMBER >= 0x1000100fL + +#include "openssl_gcm.h" + +#include <openssl/evp.h> + +/** as defined in RFC 4106 */ +#define IV_LEN 8 +#define SALT_LEN 4 +#define NONCE_LEN (IV_LEN + SALT_LEN) + +typedef struct private_aead_t private_aead_t; + +/** + * Private data of aead_t + */ +struct private_aead_t { + + /** + * Public interface + */ + aead_t public; + + /** + * The encryption key + */ + chunk_t key; + + /** + * Salt value + */ + char salt[SALT_LEN]; + + /** + * Size of the integrity check value + */ + size_t icv_size; + + /** + * The cipher to use + */ + const EVP_CIPHER *cipher; +}; + +/** + * Do the actual en/decryption in an EVP context + */ +static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv, + u_char *out, int enc) +{ + EVP_CIPHER_CTX ctx; + u_char nonce[NONCE_LEN]; + bool success = FALSE; + int len; + + memcpy(nonce, this->salt, SALT_LEN); + memcpy(nonce + SALT_LEN, iv.ptr, IV_LEN); + + EVP_CIPHER_CTX_init(&ctx); + EVP_CIPHER_CTX_set_padding(&ctx, 0); + if (!EVP_CipherInit_ex(&ctx, this->cipher, NULL, NULL, NULL, enc) || + !EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, NONCE_LEN, NULL) || + !EVP_CipherInit_ex(&ctx, NULL, NULL, this->key.ptr, nonce, enc)) + { + goto done; + } + if (!enc && !EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, this->icv_size, + data.ptr + data.len)) + { /* set ICV for verification on decryption */ + goto done; + } + if (assoc.len && !EVP_CipherUpdate(&ctx, NULL, &len, assoc.ptr, assoc.len)) + { /* set AAD if specified */ + goto done; + } + if (!EVP_CipherUpdate(&ctx, out, &len, data.ptr, data.len) || + !EVP_CipherFinal_ex(&ctx, out + len, &len)) + { /* EVP_CipherFinal_ex fails if ICV is incorrect on decryption */ + goto done; + } + if (enc && !EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, this->icv_size, + out + data.len)) + { /* copy back the ICV when encrypting */ + goto done; + } + success = TRUE; + +done: + EVP_CIPHER_CTX_cleanup(&ctx); + return success; +} + +METHOD(aead_t, encrypt, bool, + private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv, + chunk_t *encrypted) +{ + u_char *out; + + out = plain.ptr; + if (encrypted) + { + *encrypted = chunk_alloc(plain.len + this->icv_size); + out = encrypted->ptr; + } + return crypt(this, plain, assoc, iv, out, 1); +} + +METHOD(aead_t, decrypt, bool, + private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv, + chunk_t *plain) +{ + u_char *out; + + if (encrypted.len < this->icv_size) + { + return FALSE; + } + encrypted.len -= this->icv_size; + + out = encrypted.ptr; + if (plain) + { + *plain = chunk_alloc(encrypted.len); + out = plain->ptr; + } + return crypt(this, encrypted, assoc, iv, out, 0); +} + +METHOD(aead_t, get_block_size, size_t, + private_aead_t *this) +{ + return this->cipher->block_size; +} + +METHOD(aead_t, get_icv_size, size_t, + private_aead_t *this) +{ + return this->icv_size; +} + +METHOD(aead_t, get_iv_size, size_t, + private_aead_t *this) +{ + return IV_LEN; +} + +METHOD(aead_t, get_key_size, size_t, + private_aead_t *this) +{ + return this->key.len + SALT_LEN; +} + +METHOD(aead_t, set_key, bool, + private_aead_t *this, chunk_t key) +{ + if (key.len != get_key_size(this)) + { + return FALSE; + } + memcpy(this->salt, key.ptr + key.len - SALT_LEN, SALT_LEN); + memcpy(this->key.ptr, key.ptr, this->key.len); + return TRUE; +} + +METHOD(aead_t, destroy, void, + private_aead_t *this) +{ + chunk_clear(&this->key); + free(this); +} + +/* + * Described in header + */ +aead_t *openssl_gcm_create(encryption_algorithm_t algo, size_t key_size) +{ + private_aead_t *this; + + INIT(this, + .public = { + .encrypt = _encrypt, + .decrypt = _decrypt, + .get_block_size = _get_block_size, + .get_icv_size = _get_icv_size, + .get_iv_size = _get_iv_size, + .get_key_size = _get_key_size, + .set_key = _set_key, + .destroy = _destroy, + }, + ); + + switch (algo) + { + case ENCR_AES_GCM_ICV8: + this->icv_size = 8; + break; + case ENCR_AES_GCM_ICV12: + this->icv_size = 12; + break; + case ENCR_AES_GCM_ICV16: + this->icv_size = 16; + break; + default: + free(this); + return NULL; + } + + switch (algo) + { + case ENCR_AES_GCM_ICV8: + case ENCR_AES_GCM_ICV12: + case ENCR_AES_GCM_ICV16: + switch (key_size) + { + case 0: + key_size = 16; + /* FALL */ + case 16: + this->cipher = EVP_get_cipherbyname("aes-128-gcm"); + break; + case 24: + this->cipher = EVP_get_cipherbyname("aes-192-gcm"); + break; + case 32: + this->cipher = EVP_get_cipherbyname("aes-256-gcm"); + break; + default: + free(this); + return NULL; + } + break; + default: + free(this); + return NULL; + } + + if (!this->cipher) + { + free(this); + return NULL; + } + + this->key = chunk_alloc(key_size); + + return &this->public; +} + +#endif /* OPENSSL_VERSION_NUMBER */ diff --git a/src/libstrongswan/plugins/openssl/openssl_gcm.h b/src/libstrongswan/plugins/openssl/openssl_gcm.h new file mode 100644 index 000000000..12d2e8ab6 --- /dev/null +++ b/src/libstrongswan/plugins/openssl/openssl_gcm.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 Tobias Brunner + * 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. + */ + +/** + * Implements the aead_t interface using OpenSSL in GCM mode. + * + * @defgroup openssl_gcm openssl_gcm + * @{ @ingroup openssl_p + */ + +#ifndef OPENSSL_GCM_H_ +#define OPENSSL_GCM_H_ + +#include <crypto/aead.h> + +/** + * Constructor to create aead_t implementation. + * + * @param algo algorithm to implement + * @param key_size key size in bytes + * @return aead_t object, NULL if not supported + */ +aead_t *openssl_gcm_create(encryption_algorithm_t algo, size_t key_size); + +#endif /** OPENSSL_GCM_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_hmac.c b/src/libstrongswan/plugins/openssl/openssl_hmac.c index 5d05425d3..4f0bcc7c3 100644 --- a/src/libstrongswan/plugins/openssl/openssl_hmac.c +++ b/src/libstrongswan/plugins/openssl/openssl_hmac.c @@ -35,6 +35,10 @@ * THE SOFTWARE. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_HMAC + #include <openssl/evp.h> #include <openssl/hmac.h> @@ -189,3 +193,4 @@ signer_t *openssl_hmac_signer_create(integrity_algorithm_t algo) return NULL; } +#endif /* OPENSSL_NO_HMAC */ diff --git a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c index ccc426235..9c3c4040c 100644 --- a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c +++ b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c @@ -13,8 +13,10 @@ * for more details. */ +#include <openssl/opensslv.h> #include <openssl/opensslconf.h> +#if OPENSSL_VERSION_NUMBER >= 0x0090807fL #ifndef OPENSSL_NO_CMS #include "openssl_pkcs7.h" @@ -788,3 +790,4 @@ pkcs7_t *openssl_pkcs7_load(container_type_t type, va_list args) } #endif /* OPENSSL_NO_CMS */ +#endif /* OPENSSL_VERSION_NUMBER */ diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index dd6a379d2..915082234 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -43,6 +43,7 @@ #include "openssl_pkcs7.h" #include "openssl_rng.h" #include "openssl_hmac.h" +#include "openssl_gcm.h" typedef struct private_openssl_plugin_t private_openssl_plugin_t; @@ -304,6 +305,21 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(SIGNER, AUTH_HMAC_SHA2_512_256), #endif #endif /* OPENSSL_NO_HMAC */ +#if OPENSSL_VERSION_NUMBER >= 0x1000100fL +#ifndef OPENSSL_NO_AES + /* AES GCM */ + PLUGIN_REGISTER(AEAD, openssl_gcm_create), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8, 32), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 32), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 16), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 24), + PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 32), +#endif /* OPENSSL_NO_AES */ +#endif /* OPENSSL_VERSION_NUMBER */ #ifndef OPENSSL_NO_DH /* MODP DH groups */ PLUGIN_REGISTER(DH, openssl_diffie_hellman_create), @@ -366,10 +382,12 @@ METHOD(plugin_t, get_features, int, PLUGIN_SDEPEND(PUBKEY, KEY_DSA), PLUGIN_REGISTER(CERT_DECODE, openssl_crl_load, TRUE), PLUGIN_PROVIDE(CERT_DECODE, CERT_X509_CRL), +#if OPENSSL_VERSION_NUMBER >= 0x0090807fL #ifndef OPENSSL_NO_CMS PLUGIN_REGISTER(CONTAINER_DECODE, openssl_pkcs7_load, TRUE), PLUGIN_PROVIDE(CONTAINER_DECODE, CONTAINER_PKCS7), #endif /* OPENSSL_NO_CMS */ +#endif /* OPENSSL_VERSION_NUMBER */ #ifndef OPENSSL_NO_ECDH /* EC DH groups */ PLUGIN_REGISTER(DH, openssl_ec_diffie_hellman_create), @@ -470,4 +488,3 @@ plugin_t *openssl_plugin_create() return &this->public.plugin; } - diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index 926e5928c..fb86a6bf1 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -14,6 +14,10 @@ * for more details. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_RSA + #include "openssl_rsa_private_key.h" #include "openssl_rsa_public_key.h" @@ -599,3 +603,4 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type, #endif /* OPENSSL_NO_ENGINE */ } +#endif /* OPENSSL_NO_RSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c index 0da5d2514..bf71d7901 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -14,6 +14,10 @@ * for more details. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_RSA + #include "openssl_rsa_public_key.h" #include <utils/debug.h> @@ -388,3 +392,5 @@ openssl_rsa_public_key_t *openssl_rsa_public_key_load(key_type_t type, destroy(this); return NULL; } + +#endif /* OPENSSL_NO_RSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c index 8501e2cd4..8c00e6a57 100644 --- a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c +++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c @@ -13,6 +13,10 @@ * for more details. */ +#include <openssl/opensslconf.h> + +#ifndef OPENSSL_NO_SHA1 + #include "openssl_sha1_prf.h" #include <openssl/sha.h> @@ -143,3 +147,4 @@ openssl_sha1_prf_t *openssl_sha1_prf_create(pseudo_random_function_t algo) return &this->public; } +#endif /* OPENSSL_NO_SHA1 */ diff --git a/src/libstrongswan/plugins/rdrand/rdrand_rng.h b/src/libstrongswan/plugins/rdrand/rdrand_rng.h index d15a48224..3fb49ce6e 100644 --- a/src/libstrongswan/plugins/rdrand/rdrand_rng.h +++ b/src/libstrongswan/plugins/rdrand/rdrand_rng.h @@ -15,7 +15,7 @@ /** * @defgroup rdrand_rng rdrand_rng - * @{ @ingroup rdrand + * @{ @ingroup rdrand_p */ #ifndef RDRAND_RNG_H_ diff --git a/src/libstrongswan/plugins/unbound/Makefile.am b/src/libstrongswan/plugins/unbound/Makefile.am new file mode 100644 index 000000000..efb313407 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/Makefile.am @@ -0,0 +1,20 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = -rdynamic -DIPSEC_CONFDIR=\"${sysconfdir}\" + + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-unbound.la +else +plugin_LTLIBRARIES = libstrongswan-unbound.la +endif + +libstrongswan_unbound_la_SOURCES = \ + unbound_plugin.h unbound_plugin.c \ + unbound_resolver.c unbound_resolver.h \ + unbound_rr.h unbound_rr.c \ + unbound_response.h unbound_response.c + +libstrongswan_unbound_la_LDFLAGS = -module -avoid-version +libstrongswan_unbound_la_LIBADD = -lunbound -lldns diff --git a/src/libstrongswan/plugins/unbound/unbound_plugin.c b/src/libstrongswan/plugins/unbound/unbound_plugin.c new file mode 100644 index 000000000..90b95330a --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_plugin.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011-2012 Reto Guadagnini + * 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 "unbound_plugin.h" + +#include <library.h> +#include "unbound_resolver.h" + +typedef struct private_unbound_plugin_t private_unbound_plugin_t; + +/** + * private data of unbound_plugin + */ +struct private_unbound_plugin_t { + + /** + * public functions + */ + unbound_plugin_t public; +}; + +METHOD(plugin_t, get_name, char*, + private_unbound_plugin_t *this) +{ + return "unbound"; +} + +METHOD(plugin_t, destroy, void, + private_unbound_plugin_t *this) +{ + lib->resolver->remove_resolver(lib->resolver, unbound_resolver_create); + free(this); +} + +/* + * see header file + */ +plugin_t *unbound_plugin_create() +{ + private_unbound_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .destroy = _destroy, + }, + }, + ); + + lib->resolver->add_resolver(lib->resolver, unbound_resolver_create); + + return &this->public.plugin; +} diff --git a/src/libstrongswan/plugins/unbound/unbound_plugin.h b/src/libstrongswan/plugins/unbound/unbound_plugin.h new file mode 100644 index 000000000..1f0d36454 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011-2012 Reto Guadagnini + * 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 unbound_p unbound + * @ingroup plugins + * + * @defgroup unbound_plugin unbound_plugin + * @{ @ingroup unbound_p + */ + +#ifndef unbound_PLUGIN_H_ +#define unbound_PLUGIN_H_ + +#include <plugins/plugin.h> + +typedef struct unbound_plugin_t unbound_plugin_t; + +/** + * Plugin implementing the resolver interface using the libunbound DNS library. + */ +struct unbound_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +#endif /** unbound_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/unbound/unbound_resolver.c b/src/libstrongswan/plugins/unbound/unbound_resolver.c new file mode 100644 index 000000000..44a2c764b --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_resolver.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2011-2012 Reto Guadagnini + * 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 <unbound.h> +#include <errno.h> +#include <ldns/ldns.h> +#include <string.h> + +#include <library.h> +#include <utils/debug.h> + +#include "unbound_resolver.h" +#include "unbound_response.h" + +/* DNS resolver configuration and DNSSEC trust anchors */ +#define RESOLV_CONF_FILE "/etc/resolv.conf" +#define TRUST_ANCHOR_FILE IPSEC_CONFDIR "/ipsec.d/dnssec.keys" + +typedef struct private_resolver_t private_resolver_t; + +/** + * private data of a unbound_resolver_t object. + */ +struct private_resolver_t { + + /** + * Public data + */ + resolver_t public; + + /** + * private unbound resolver handle (unbound context) + */ + struct ub_ctx *ctx; +}; + +/** + * query method implementation + */ +METHOD(resolver_t, query, resolver_response_t*, + private_resolver_t *this, char *domain, rr_class_t rr_class, + rr_type_t rr_type) +{ + unbound_response_t *response = NULL; + struct ub_result *result = NULL; + int ub_retval; + + ub_retval = ub_resolve(this->ctx, domain, rr_type, rr_class, &result); + if (ub_retval) + { + DBG1(DBG_LIB, "unbound resolver error: %s", ub_strerror(ub_retval)); + ub_resolve_free(result); + return NULL; + } + + response = unbound_response_create_frm_libub_response(result); + if (!response) + { + DBG1(DBG_LIB, "unbound resolver failed to create response"); + ub_resolve_free(result); + return NULL; + } + ub_resolve_free(result); + + return (resolver_response_t*)response; +} + +/** + * destroy method implementation + */ +METHOD(resolver_t, destroy, void, + private_resolver_t *this) +{ + ub_ctx_delete(this->ctx); + free(this); +} + +/* + * Described in header. + */ +resolver_t *unbound_resolver_create(void) +{ + private_resolver_t *this; + int ub_retval = 0; + char *resolv_conf_file; + char *trust_anchor_file; + + resolv_conf_file = lib->settings->get_str(lib->settings, + "libstrongswan.plugins.unbound.resolv_conf", + RESOLV_CONF_FILE); + + trust_anchor_file = lib->settings->get_str(lib->settings, + "libstrongswan.plugins.unbound.trust_anchors", + TRUST_ANCHOR_FILE); + + INIT(this, + .public = { + .query = _query, + .destroy = _destroy, + }, + ); + + this->ctx = ub_ctx_create(); + if (!this->ctx) + { + DBG1(DBG_LIB, "failed to create unbound resolver context"); + destroy(this); + return NULL; + } + + DBG1(DBG_CFG, "loading unbound resolver config from '%s'", resolv_conf_file); + ub_retval = ub_ctx_resolvconf(this->ctx, resolv_conf_file); + if (ub_retval) + { + DBG1(DBG_CFG, "failed to read the resolver config: %s (%s)", + ub_strerror(ub_retval), strerror(errno)); + destroy(this); + return NULL; + } + + DBG1(DBG_CFG, "loading unbound trust anchors from '%s'", trust_anchor_file); + ub_retval = ub_ctx_add_ta_file(this->ctx, trust_anchor_file); + if (ub_retval) + { + DBG1(DBG_CFG, "failed to load trust anchors: %s (%s)", + ub_strerror(ub_retval), strerror(errno)); + } + + return &this->public; +} + diff --git a/src/libstrongswan/plugins/unbound/unbound_resolver.h b/src/libstrongswan/plugins/unbound/unbound_resolver.h new file mode 100644 index 000000000..818a717b8 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_resolver.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2011-2012 Reto Guadagnini + * 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 unbound_resolver unbound_resolver + * @{ @ingroup unbound_p + */ + +#ifndef unbound_RESOLVER_H_ +#define unbound_RESOLVER_H_ + +/** + * Create a resolver_t instance. + */ +resolver_t *unbound_resolver_create(void); + +#endif /** LIBunbound_RESOLVER_H_ @}*/ diff --git a/src/libstrongswan/plugins/unbound/unbound_response.c b/src/libstrongswan/plugins/unbound/unbound_response.c new file mode 100644 index 000000000..6f6c25e89 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_response.c @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 <resolver/resolver_response.h> +#include <resolver/rr.h> +#include "unbound_rr.h" +#include "unbound_response.h" + +#include <library.h> +#include <utils/debug.h> + +#include <unbound.h> +#include <ldns/ldns.h> + +typedef struct private_unbound_response_t private_unbound_response_t; + +/** + * private data of an unbound_response_t object. + */ +struct private_unbound_response_t { + + /** + * Public data + */ + unbound_response_t public; + + /** + * Original question string + */ + char* query_name; + + /** + * Canonical name of the response + */ + char* canon_name; + + /** + * Are the some RRs in the RRset of this response? + */ + bool has_data; + + /* + * Does the queried name exist? + */ + bool query_name_exist; + + /** + * DNSSEC security state + */ + dnssec_status_t security_state; + + /** + * RRset + */ + rr_set_t *rr_set; +}; + +METHOD(resolver_response_t, get_query_name, char*, + private_unbound_response_t *this) +{ + return this->query_name; +} + +METHOD(resolver_response_t, get_canon_name, char*, + private_unbound_response_t *this) +{ + return this->canon_name; +} + +METHOD(resolver_response_t, has_data, bool, + private_unbound_response_t *this) +{ + return this->has_data; +} + +METHOD(resolver_response_t, query_name_exist, bool, + private_unbound_response_t *this) +{ + return this->query_name_exist; +} + +METHOD(resolver_response_t, get_security_state, dnssec_status_t, + private_unbound_response_t *this) +{ + return this->security_state; +} + +METHOD(resolver_response_t, get_rr_set, rr_set_t*, + private_unbound_response_t *this) +{ + return this->rr_set; +} + +METHOD(resolver_response_t, destroy, void, + private_unbound_response_t *this) +{ + free(this->query_name); + free(this->canon_name); + DESTROY_IF(this->rr_set); + free(this); +} + +/* + * Described in header. + */ +unbound_response_t *unbound_response_create_frm_libub_response( + struct ub_result *libub_response) +{ + private_unbound_response_t *this = NULL; + + INIT(this, + .public = { + .interface = { + .get_query_name = _get_query_name, + .get_canon_name = _get_canon_name, + .has_data = _has_data, + .query_name_exist = _query_name_exist, + .get_security_state = _get_security_state, + .get_rr_set = _get_rr_set, + .destroy = _destroy, + }, + }, + ); + + this->query_name = strdup(libub_response->qname); + + if (libub_response->canonname) + { + this->canon_name = strdup(libub_response->canonname); + } + + this->has_data = libub_response->havedata; + + this->query_name_exist = !(libub_response->nxdomain); + + if (libub_response->secure) + { + this->security_state = SECURE; + } + else if (libub_response->bogus) + { + this->security_state = BOGUS; + } + else + { + this->security_state = INDETERMINATE; + } + + /** + * Create RRset + */ + if (this->query_name_exist && this->has_data) + { + ldns_pkt *dns_pkt = NULL; + ldns_rr_list *orig_rr_list = NULL; + size_t orig_rr_count; + ldns_rr *orig_rr = NULL; + ldns_rdf *orig_rdf = NULL; + ldns_status status; + linked_list_t *rr_list = NULL, *rrsig_list = NULL; + unbound_rr_t *rr = NULL; + int i; + + /**Parse the received DNS packet using the ldns library */ + status = ldns_wire2pkt(&dns_pkt, libub_response->answer_packet, + libub_response->answer_len); + + if (status != LDNS_STATUS_OK) + { + DBG1(DBG_LIB, "failed to parse DNS packet"); + destroy(this); + return NULL; + } + + /* Create a list with the queried RRs. If there are corresponding RRSIGs + * create also a list with these. + */ + rr_list = linked_list_create(); + + orig_rr_list = ldns_pkt_get_section_clone(dns_pkt, LDNS_SECTION_ANSWER); + orig_rr_count = ldns_rr_list_rr_count(orig_rr_list); + + for (i = 0; i < orig_rr_count; i++) + { + orig_rr = ldns_rr_list_rr(orig_rr_list, i); + + if (ldns_rr_get_type(orig_rr) == libub_response->qtype && + ldns_rr_get_class(orig_rr) == libub_response->qclass) + { + /* RR is part of the queried RRset. + * => add it to the list of Resource Records. + */ + rr = unbound_rr_create_frm_ldns_rr(orig_rr); + if (rr) + { + rr_list->insert_last(rr_list, rr); + } + else + { + DBG1(DBG_LIB, "failed to create RR"); + } + } + + if (ldns_rr_get_type(orig_rr) == LDNS_RR_TYPE_RRSIG) + { + orig_rdf = ldns_rr_rrsig_typecovered(orig_rr); + if (!orig_rdf) + { + DBG1(DBG_LIB, "failed to get the type covered by an RRSIG"); + } + else if (ldns_rdf2native_int16(orig_rdf) == libub_response->qtype) + { + /* The current RR represent a signature (RRSIG) + * which belongs to the queried RRset. + * => add it to the list of signatures. + */ + rr = unbound_rr_create_frm_ldns_rr(orig_rr); + if (rr) + { + if (!rrsig_list) + { + rrsig_list = linked_list_create(); + } + rrsig_list->insert_last(rrsig_list, rr); + } + else + { + DBG1(DBG_LIB, "failed to create RRSIG"); + } + } + else + { + DBG1(DBG_LIB, "failed to determine the RR type " + "covered by RRSIG RR"); + } + } + } + /** + * Create the RRset for which the query was performed. + */ + this->rr_set = rr_set_create(rr_list, rrsig_list); + + ldns_pkt_free(dns_pkt); + ldns_rr_list_free(orig_rr_list); + } + return &this->public; +} diff --git a/src/libstrongswan/plugins/unbound/unbound_response.h b/src/libstrongswan/plugins/unbound/unbound_response.h new file mode 100644 index 000000000..c82f39d45 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_response.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 unbound_response unbound_response + * @{ @ingroup unbound_p + */ + +#ifndef UNBOUND_RESPONSE_H_ +#define UNBOUND_RESPONSE_H_ + +#include <resolver/resolver_response.h> +#include <unbound.h> + +typedef struct unbound_response_t unbound_response_t; + +/** + * Implementation of the resolver_response interface using libunbound. + * + */ +struct unbound_response_t { + + /** + * Implements the resolver_response interface + */ + resolver_response_t interface; +}; + +/** + * Create an unbound_response instance from a response of the unbound library. + * + * @param response a response of the unbound library + * @return an unbound_response conforming to the resolver_response + * interface, or NULL on failure + */ +unbound_response_t *unbound_response_create_frm_libub_response( + struct ub_result *response); + +#endif /** UNBOUND_RESPONSE_H_ @}*/ diff --git a/src/libstrongswan/plugins/unbound/unbound_rr.c b/src/libstrongswan/plugins/unbound/unbound_rr.c new file mode 100644 index 000000000..97c3b1933 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_rr.c @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 <resolver/rr.h> + +#include <library.h> +#include <utils/debug.h> + +#include <stdlib.h> +#include <string.h> + +#include "unbound_rr.h" + +typedef struct private_unbound_rr_t private_unbound_rr_t; + +/** + * private data of an unbound_rr_t object. + */ +struct private_unbound_rr_t { + + /** + * Public data + */ + unbound_rr_t public; + + /** + * Owner name + */ + char* name; + + /** + * Type + */ + rr_type_t type; + + /** + * Class + */ + rr_class_t class; + + /** + * TTL + */ + uint32_t ttl; + + /** + * Size of the rdata field in octets + */ + uint16_t size; + + /** + * RDATA field (array of bytes in network order) + */ + u_char *rdata; +}; + +METHOD(rr_t, get_name, char *, + private_unbound_rr_t *this) +{ + return this->name; +} + +METHOD(rr_t, get_type, rr_type_t, + private_unbound_rr_t *this) +{ + return this->type; +} + +METHOD(rr_t, get_class, rr_class_t, + private_unbound_rr_t *this) +{ + return this->class; +} + +METHOD(rr_t, get_ttl, uint32_t, + private_unbound_rr_t *this) +{ + return this->ttl; +} + +METHOD(rr_t, get_rdata, chunk_t, + private_unbound_rr_t *this) +{ + return chunk_create(this->rdata, this->size); +} + +METHOD(rr_t, destroy, void, + private_unbound_rr_t *this) +{ + free(this->name); + free(this->rdata); + free(this); +} + +/* + * Described in header. + */ +unbound_rr_t *unbound_rr_create_frm_ldns_rr(ldns_rr *rr) +{ + private_unbound_rr_t *this; + ldns_status status; + ldns_buffer *buf; + int i; + + INIT(this, + .public = { + .interface = { + .get_name = _get_name, + .get_type = _get_type, + .get_class = _get_class, + .get_ttl = _get_ttl, + .get_rdata = _get_rdata, + .destroy = _destroy, + }, + }, + ); + + this->name = ldns_rdf2str(ldns_rr_owner(rr)); + if (!this->name) + { + DBG1(DBG_LIB, "failed to parse the owner name of a DNS RR"); + _destroy(this); + return NULL; + } + + this->type = ldns_rr_get_type(rr); + this->class = ldns_rr_get_class(rr); + this->ttl = ldns_rr_ttl(rr); + for(i = 0; i < ldns_rr_rd_count(rr); i++) + { + this->size += ldns_rdf_size(ldns_rr_rdf(rr, i)); + } + + /** + * The ldns library splits the RDATA field of a RR in various rdf. + * Here we reassemble these rdf to get the RDATA field of the RR. + */ + buf = ldns_buffer_new(LDNS_MIN_BUFLEN); + /* The buffer will be resized automatically by ldns_rr_rdata2buffer_wire() */ + status = ldns_rr_rdata2buffer_wire(buf, rr); + + if (status != LDNS_STATUS_OK) + { + DBG1(DBG_LIB, "failed to get the RDATA field of a DNS RR"); + _destroy(this); + return NULL; + } + + this->rdata = ldns_buffer_export(buf); + + return &this->public; +} diff --git a/src/libstrongswan/plugins/unbound/unbound_rr.h b/src/libstrongswan/plugins/unbound/unbound_rr.h new file mode 100644 index 000000000..d7c114f86 --- /dev/null +++ b/src/libstrongswan/plugins/unbound/unbound_rr.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 unbound_rr unbound_rr + * @{ @ingroup unbound_p + */ + +#ifndef UNBOUND_RR_H_ +#define UNBOUND_RR_H_ + +#include <resolver/rr.h> +#include <ldns/ldns.h> + +typedef struct unbound_rr_t unbound_rr_t; + +/** + * Implementation of the Resource Record interface using libunbound and libldns. + */ +struct unbound_rr_t { + + /** + * Implements the Resource Record interface + */ + rr_t interface; +}; + +/** + * Create an unbound_rr instance from a Resource Record given by + * a ldns_struct_rr from the ldns library. + * + * @return Resource Record, NULL on error + */ +unbound_rr_t *unbound_rr_create_frm_ldns_rr(ldns_rr *rr); + +#endif /** UNBOUND_RR_H_ @}*/ diff --git a/src/libstrongswan/resolver/resolver.h b/src/libstrongswan/resolver/resolver.h new file mode 100644 index 000000000..5be52b8b1 --- /dev/null +++ b/src/libstrongswan/resolver/resolver.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2011-2012 Reto Guadagnini + * 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 resolveri resolver + * @{ @ingroup resolver + */ + +#ifndef RESOLVER_H_ +#define RESOLVER_H_ + +typedef struct resolver_t resolver_t; + +/** + * Constructor function which creates DNS resolver instances. + */ +typedef resolver_t* (*resolver_constructor_t)(void); + +#include <resolver/resolver_response.h> +#include <resolver/rr_set.h> +#include <resolver/rr.h> + +/** + * Interface of a security-aware DNS resolver. + * + */ +struct resolver_t { + + /** + * Perform a DNS query. + * + * @param domain domain (FQDN) to query + * @param rr_class class of the desired RRs + * @param rr_type type of the desired RRs + * @return response to the query, NULL on failure + */ + resolver_response_t *(*query)(resolver_t *this, char *domain, + rr_class_t rr_class, rr_type_t rr_type); + + /** + * Destroy the resolver instance. + */ + void (*destroy)(resolver_t *this); +}; + +#endif /** RESOLVER_H_ @}*/ diff --git a/src/libstrongswan/resolver/resolver_manager.c b/src/libstrongswan/resolver/resolver_manager.c new file mode 100644 index 000000000..8effe469a --- /dev/null +++ b/src/libstrongswan/resolver/resolver_manager.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2011-2012 Reto Guadagnini + * 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 "resolver_manager.h" + +#include <utils/debug.h> + +typedef struct private_resolver_manager_t private_resolver_manager_t; + +/** + * private data of resolver_manager + */ +struct private_resolver_manager_t { + + /** + * public functions + */ + resolver_manager_t public; + + /** + * constructor function to create resolver instances + */ + resolver_constructor_t constructor; +}; + +METHOD(resolver_manager_t, add_resolver, void, + private_resolver_manager_t *this, resolver_constructor_t constructor) +{ + if (!this->constructor) + { + this->constructor = constructor; + } +} + +METHOD(resolver_manager_t, remove_resolver, void, + private_resolver_manager_t *this, resolver_constructor_t constructor) +{ + if (this->constructor == constructor) + { + this->constructor = NULL; + } +} + +METHOD(resolver_manager_t, create, resolver_t*, + private_resolver_manager_t *this) +{ + return this->constructor(); +} + +METHOD(resolver_manager_t, destroy, void, + private_resolver_manager_t *this) +{ + free(this); +} + +/* + * See header + */ +resolver_manager_t *resolver_manager_create() +{ + private_resolver_manager_t *this; + + INIT(this, + .public = { + .add_resolver = _add_resolver, + .remove_resolver = _remove_resolver, + .create = _create, + .destroy = _destroy, + }, + ); + + return &this->public; +} + diff --git a/src/libstrongswan/resolver/resolver_manager.h b/src/libstrongswan/resolver/resolver_manager.h new file mode 100644 index 000000000..6ea22aa24 --- /dev/null +++ b/src/libstrongswan/resolver/resolver_manager.h @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2011-2012 Reto Guadagnini + * 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 resolver_manager resolver_manager +* @{ @ingroup resolver +*/ + +#ifndef RESOLVER_MANAGER_H_ +#define RESOLVER_MANAGER_H_ + +typedef struct resolver_manager_t resolver_manager_t; + +#include <resolver/resolver.h> + +/** + * The resolver_manager manages the resolver implementations and + * creates instances of them. + * + * A resolver plugin is registered by providing its constructor function + * to the manager. The manager creates instances of the resolver plugin + * using the registered constructor function. + */ +struct resolver_manager_t { + + /** + * Register a resolver implementation. + * + * @param constructor resolver constructor function + */ + void (*add_resolver)(resolver_manager_t *this, + resolver_constructor_t constructor); + + /** + * Unregister a previously registered resolver implementation. + * + * @param constructor resolver constructor function to unregister + */ + void (*remove_resolver)(resolver_manager_t *this, + resolver_constructor_t constructor); + + /** + * Get a new resolver instance. + * + * @return resolver instance. + */ + resolver_t* (*create)(resolver_manager_t *this); + + /** + * Destroy a resolver_manager instance. + */ + void (*destroy)(resolver_manager_t *this); +}; + +/** + * Create a resolver_manager instance. + */ +resolver_manager_t *resolver_manager_create(); + +#endif /** RESOLVER_MANAGER_H_ @}*/ diff --git a/src/libstrongswan/resolver/resolver_response.h b/src/libstrongswan/resolver/resolver_response.h new file mode 100644 index 000000000..e45fb6401 --- /dev/null +++ b/src/libstrongswan/resolver/resolver_response.h @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 rsolver_response resolver_response + * @{ @ingroup resolver + */ + +#ifndef RESOLVER_RESPONSE_H_ +#define RESOLVER_RESPONSE_H_ + +typedef struct resolver_response_t resolver_response_t; +typedef enum dnssec_status_t dnssec_status_t; + +#include <library.h> +#include <resolver/rr_set.h> + +/** + * DNSSEC security state. + * + * DNSSEC security state, which a security aware resolver is able determine + * according to RFC 4033. + */ +enum dnssec_status_t { + /** + * The validating resolver has a trust anchor, has a chain of + * trust, and is able to verify all the signatures in the response. + * [RFC4033] + */ + SECURE, + /** + * The validating resolver has a trust anchor, a chain of + * trust, and, at some delegation point, signed proof of the + * non-existence of a DS record. This indicates that subsequent + * branches in the tree are provably insecure. A validating resolver + * may have a local policy to mark parts of the domain space as + * insecure. [RFC4033] + */ + INSECURE, + /** + * The validating resolver has a trust anchor and a secure + * delegation indicating that subsidiary data is signed, but the + * response fails to validate for some reason: missing signatures, + * expired signatures, signatures with unsupported algorithms, data + * missing that the relevant NSEC RR says should be present, and so + * forth. [RFC4033] + */ + BOGUS, + /** + * There is no trust anchor that would indicate that a + * specific portion of the tree is secure. This is the default + * operation mode. [RFC4033] + */ + INDETERMINATE, +}; + + +/** + * A response of the DNS resolver to a DNS query. + * + * A response represents the answer of the Domain Name System to a query. + * It contains the RRset with the queried Resource Records and additional + * information. + */ +struct resolver_response_t { + + /** + * Get the original question string. + * + * The string to which the returned pointer points, is still owned + * by the resolver_response. Clone it if necessary. + * + * @return the queried name + */ + char *(*get_query_name)(resolver_response_t *this); + + /** + * Get the canonical name of the result. + * + * The string to which the returned pointer points, is still owned + * by the resolver_response. Clone it if necessary. + * + * @return - canonical name of result + * - NULL, if result has no canonical name + */ + char *(*get_canon_name)(resolver_response_t *this); + + /** + * Does the RRset of this response contain some Resource Records? + * + * Returns TRUE if the RRset of this response contains some RRs + * (RRSIG Resource Records are ignored). + * + * @return + * - TRUE, if there are some RRs in the RRset + * - FALSE, otherwise + */ + bool (*has_data)(resolver_response_t *this); + + /** + * Does the queried name exist? + * + * @return + * - TRUE, if the queried name exists + * - FALSE, otherwise + */ + bool (*query_name_exist)(resolver_response_t *this); + + /** + * Get the DNSSEC security state of the response. + * + * @return DNSSEC security state + */ + dnssec_status_t (*get_security_state)(resolver_response_t *this); + + /** + * Get the RRset with all Resource Records of this response. + * + * @return - RRset + * - NULL if there is no data or the query name + * does not exist + */ + rr_set_t *(*get_rr_set)(resolver_response_t *this); + + /** + * Destroy this response. + */ + void (*destroy) (resolver_response_t *this); +}; + +#endif /** RR_SET_H_ @}*/ diff --git a/src/libstrongswan/resolver/rr.h b/src/libstrongswan/resolver/rr.h new file mode 100644 index 000000000..109ec5135 --- /dev/null +++ b/src/libstrongswan/resolver/rr.h @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 rr rr + * @{ @ingroup resolver + */ + +#ifndef RR_H_ +#define RR_H_ + +typedef struct rr_t rr_t; +typedef enum rr_type_t rr_type_t; +typedef enum rr_class_t rr_class_t; + +#include <library.h> + +/** + * Resource Record types. + * + * According to www.iana.org/assignments/dns-parameters (version 2012-03-13). + */ +enum rr_type_t { + /** a host address */ + RR_TYPE_A = 1, + /** an authoritative name server */ + RR_TYPE_NS = 2, + //** a mail destination (OBSOLETE - use MX */ + RR_TYPE_MD = 3, + /** a mail forwarder (OBSOLETE - use MX) */ + RR_TYPE_MF = 4, + /** the canonical name for an alias */ + RR_TYPE_CNAME = 5, + /** marks the start of a zone of authority */ + RR_TYPE_SOA = 6, + /** a mailbox domain name (EXPERIMENTAL) */ + RR_TYPE_MB = 7, + /** a mail group member (EXPERIMENTAL) */ + RR_TYPE_MG = 8, + /** a mail rename domain name (EXPERIMENTAL) */ + RR_TYPE_MR = 9, + /** a null RR (EXPERIMENTAL) */ + RR_TYPE_NULL = 10, + /** a well known service description */ + RR_TYPE_WKS = 11, + /** a domain name pointer */ + RR_TYPE_PTR = 12, + /** host information */ + RR_TYPE_HINFO = 13, + /** mailbox or mail list information */ + RR_TYPE_MINFO = 14, + /** mail exchange */ + RR_TYPE_MX = 15, + /** text strings */ + RR_TYPE_TXT = 16, + /** for Responsible Person */ + RR_TYPE_RP = 17, + /** for AFS Data Base location */ + RR_TYPE_AFSDB = 18, + /** for X.25 PSDN address */ + RR_TYPE_X25 = 19, + /** for ISDN address */ + RR_TYPE_ISDN = 20, + /** for Route Through */ + RR_TYPE_RT = 21, + /** for NSAP address, NSAP style A record */ + RR_TYPE_NSAP = 22, + /** for domain name pointer, NSAP style */ + RR_TYPE_NSAP_PTR = 23, + /** for security signature */ + RR_TYPE_SIG = 24, + /** for security key */ + RR_TYPE_KEY = 25, + /** X.400 mail mapping information */ + RR_TYPE_PX = 26, + /** Geographical Position */ + RR_TYPE_GPOS = 27, + /** ipv6 address */ + RR_TYPE_AAAA = 28, + /** Location Information */ + RR_TYPE_LOC = 29, + /** Next Domain (OBSOLETE) */ + RR_TYPE_NXT = 30, + /** Endpoint Identifier */ + RR_TYPE_EID = 31, + /** Nimrod Locator */ + RR_TYPE_NIMLOC = 32, + /** Server Selection */ + RR_TYPE_SRV = 33, + /** ATM Address */ + RR_TYPE_ATMA = 34, + /** Naming Authority Pointer */ + RR_TYPE_NAPTR = 35, + /** Key Exchanger */ + RR_TYPE_KX = 36, + /** CERT */ + RR_TYPE_CERT = 37, + /** A6 (OBSOLETE - use AAAA) */ + RR_TYPE_A6 = 38, + /** DNAME */ + RR_TYPE_DNAME = 39, + /** SINK */ + RR_TYPE_SINK = 40, + /** OPT */ + RR_TYPE_OPT = 41, + /** APL */ + RR_TYPE_APL = 42, + /** Delegation Signer */ + RR_TYPE_DS = 43, + /** SSH Key Fingerprint */ + RR_TYPE_SSHFP = 44, + /** IPSECKEY */ + RR_TYPE_IPSECKEY = 45, + /** RRSIG */ + RR_TYPE_RRSIG = 46, + /** NSEC */ + RR_TYPE_NSEC = 47, + /** DNSKEY */ + RR_TYPE_DNSKEY = 48, + /** DHCID */ + RR_TYPE_DHCID = 49, + /** NSEC3 */ + RR_TYPE_NSEC3 = 50, + /** NSEC3PARAM */ + RR_TYPE_NSEC3PARAM = 51, + + /** Unassigned 52-54 */ + + /** Host Identity Protocol */ + RR_TYPE_HIP = 55, + /** NINFO */ + RR_TYPE_NINFO = 56, + /** RKEY */ + RR_TYPE_RKEY = 57, + /** Trust Anchor LINK */ + RR_TYPE_TALINK = 58, + /** Child DS */ + RR_TYPE_CDS = 59, + + /** Unassigned 60-98 */ + + /** SPF */ + RR_TYPE_SPF = 99, + /** UINFO */ + RR_TYPE_UINFO = 100, + /** UID */ + RR_TYPE_UID = 101, + /** GID */ + RR_TYPE_GID = 102, + /** UNSPEC */ + RR_TYPE_UNSPEC = 103, + + /** Unassigned 104-248 */ + + /** Transaction Key */ + RR_TYPE_TKEY = 249, + /** Transaction Signature */ + RR_TYPE_TSIG = 250, + /** incremental transfer */ + RR_TYPE_IXFR = 251, + /** transfer of an entire zone */ + RR_TYPE_AXFR = 252, + /** mailbox-related RRs (MB, MG or MR) */ + RR_TYPE_MAILB = 253, + /** mail agent RRs (OBSOLETE - see MX) */ + RR_TYPE_MAILA = 254, + /** A request for all records */ + RR_TYPE_ANY = 255, + /** URI */ + RR_TYPE_URI = 256, + /** Certification Authority Authorization */ + RR_TYPE_CAA = 257, + + /** Unassigned 258-32767 */ + + /** DNSSEC Trust Authorities */ + RR_TYPE_TA = 32768, + /** DNSSEC Lookaside Validation */ + RR_TYPE_DLV = 32769, + + /** Unassigned 32770-65279 */ + + /** Private use 65280-65534 */ + + /** Reserved 65535 */ +}; + + +/** + * Resource Record CLASSes + */ +enum rr_class_t { + /** Internet */ + RR_CLASS_IN = 1, + /** Chaos */ + RR_CLASS_CH = 3, + /** Hesiod */ + RR_CLASS_HS = 4, + /** further CLASSes: http://wwwiana.org/assignments/dns-parameters */ +}; + + +/** + * A DNS Resource Record. + * + * Represents a Resource Record of the Domain Name System + * as defined in RFC 1035. + * + */ +struct rr_t { + + /** + * Get the NAME of the owner of this RR. + * + * @return owner name as string + */ + char *(*get_name)(rr_t *this); + + /** + * Get the type of this RR. + * + * @return RR type + */ + rr_type_t (*get_type)(rr_t *this); + + /** + * Get the class of this RR. + * + * @return RR class + */ + rr_class_t (*get_class)(rr_t *this); + + /** + * Get the Time to Live (TTL) of this RR. + * + * @return Time to Live + */ + uint32_t (*get_ttl)(rr_t *this); + + /** + * Get the content of the RDATA field as chunk. + * + * The data pointed by the chunk is still owned by the RR. + * Clone it if needed. + * + * @return RDATA field as chunk + */ + chunk_t (*get_rdata)(rr_t *this); + + /** + * Destroy the Resource Record. + */ + void (*destroy) (rr_t *this); +}; + +#endif /** RR_H_ @}*/ diff --git a/src/libstrongswan/resolver/rr_set.c b/src/libstrongswan/resolver/rr_set.c new file mode 100644 index 000000000..dea5c4086 --- /dev/null +++ b/src/libstrongswan/resolver/rr_set.c @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 "rr_set.h" + +#include <library.h> +#include <utils/debug.h> + +typedef struct private_rr_set_t private_rr_set_t; + +/** +* private data of the rr_set +*/ +struct private_rr_set_t { + + /** + * public functions + */ + rr_set_t public; + + /** + * List of Resource Records which form the RRset + */ + linked_list_t *rr_list; + + /** + * List of the signatures (RRSIGs) of the Resource Records contained in + * this set + */ + linked_list_t *rrsig_list; +}; + +METHOD(rr_set_t, create_rr_enumerator, enumerator_t*, + private_rr_set_t *this) +{ + return this->rr_list->create_enumerator(this->rr_list); +} + +METHOD(rr_set_t, create_rrsig_enumerator, enumerator_t*, + private_rr_set_t *this) +{ + if (this->rrsig_list) + { + return this->rrsig_list->create_enumerator(this->rrsig_list); + } + return NULL; +} + +METHOD(rr_set_t, destroy, void, + private_rr_set_t *this) +{ + this->rr_list->destroy_offset(this->rr_list, + offsetof(rr_t, destroy)); + if (this->rrsig_list) + { + this->rrsig_list->destroy_offset(this->rrsig_list, + offsetof(rr_t, destroy)); + } + free(this); +} + +/* + * see header + */ +rr_set_t *rr_set_create(linked_list_t *list_of_rr, linked_list_t *list_of_rrsig) +{ + private_rr_set_t *this; + + INIT(this, + .public = { + .create_rr_enumerator = _create_rr_enumerator, + .create_rrsig_enumerator = _create_rrsig_enumerator, + .destroy = _destroy, + }, + ); + + if (list_of_rr == NULL) + { + DBG1(DBG_LIB, "could not create a rr_set without a list_of_rr"); + _destroy(this); + return NULL; + } + this->rr_list = list_of_rr; + this->rrsig_list = list_of_rrsig; + + return &this->public; +} + diff --git a/src/libstrongswan/resolver/rr_set.h b/src/libstrongswan/resolver/rr_set.h new file mode 100644 index 000000000..5a1737a05 --- /dev/null +++ b/src/libstrongswan/resolver/rr_set.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2012 Reto Guadagnini + * 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 rr_set rr_set + * @{ @ingroup resolver + */ + +#ifndef RR_SET_H_ +#define RR_SET_H_ + +typedef struct rr_set_t rr_set_t; + +#include <library.h> +#include <collections/enumerator.h> +#include <collections/linked_list.h> + +/** + * A set of DNS Resource Records. + * + * Represents a RRset as defined in RFC 2181. This RRset consists of a set of + * Resource Records with the same label, class and type but different data. + * + * The DNSSEC signature Resource Records (RRSIGs) which sign the RRs of this set + * are also part of an object of this type. + */ +struct rr_set_t { + + /** + * Create an enumerator over all Resource Records of this RRset. + * + * @note The enumerator's position is invalid before the first call + * to enumerate(). + * + * @return enumerator over Resource Records + */ + enumerator_t *(*create_rr_enumerator)(rr_set_t *this); + + /** + * Create an enumerator over all RRSIGs of this RRset + * + * @note The enumerator's position is invalid before the first call + * to enumerate(). + * + * @return enumerator over RRSIG Resource Records, + * NULL if there are no RRSIGs for this RRset + */ + enumerator_t *(*create_rrsig_enumerator)(rr_set_t *this); + + /** + * Destroy this RRset with all its Resource Records. + */ + void (*destroy) (rr_set_t *this); +}; + +/** + * Create an rr_set instance. + * + * @param list_of_rr list of Resource Records which form this RRset + * @param list_of_rrsig list of the signatures (RRSIGs) of the + * Resource Records of this set + * @return Resource Record set, NULL on failure + */ +rr_set_t *rr_set_create(linked_list_t *list_of_rr, + linked_list_t *list_of_rrsig); + +#endif /** RR_SET_H_ @}*/ diff --git a/src/libstrongswan/selectors/traffic_selector.c b/src/libstrongswan/selectors/traffic_selector.c index 87e57095c..ff8285f8c 100644 --- a/src/libstrongswan/selectors/traffic_selector.c +++ b/src/libstrongswan/selectors/traffic_selector.c @@ -174,7 +174,24 @@ static u_int8_t calc_netbits(private_traffic_selector_t *this) /** * internal generic constructor */ -static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, ts_type_t type, u_int16_t from_port, u_int16_t to_port); +static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, + ts_type_t type, u_int16_t from_port, u_int16_t to_port); + +/** + * Check if TS contains "opaque" ports + */ +static bool is_opaque(private_traffic_selector_t *this) +{ + return this->from_port == 0xffff && this->to_port == 0; +} + +/** + * Check if TS contains "any" ports + */ +static bool is_any(private_traffic_selector_t *this) +{ + return this->from_port == 0 && this->to_port == 0xffff; +} /** * Described in header. @@ -248,7 +265,7 @@ int traffic_selector_printf_hook(printf_hook_data_t *data, /* check if we have protocol and/or port selectors */ has_proto = this->protocol != 0; - has_ports = !(this->from_port == 0 && this->to_port == 0xFFFF); + has_ports = !is_any(this); if (!has_proto && !has_ports) { @@ -283,8 +300,9 @@ int traffic_selector_printf_hook(printf_hook_data_t *data, { if (this->from_port == this->to_port) { - struct servent *serv = getservbyport(htons(this->from_port), serv_proto); + struct servent *serv; + serv = getservbyport(htons(this->from_port), serv_proto); if (serv) { written += print_in_hook(data, "%s", serv->s_name); @@ -294,9 +312,14 @@ int traffic_selector_printf_hook(printf_hook_data_t *data, written += print_in_hook(data, "%d", this->from_port); } } + else if (is_opaque(this)) + { + written += print_in_hook(data, "OPAQUE"); + } else { - written += print_in_hook(data, "%d-%d", this->from_port, this->to_port); + written += print_in_hook(data, "%d-%d", + this->from_port, this->to_port); } } @@ -305,24 +328,55 @@ int traffic_selector_printf_hook(printf_hook_data_t *data, return written; } -/** - * Implements traffic_selector_t.get_subset - */ -static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_traffic_selector_t *other) +METHOD(traffic_selector_t, get_subset, traffic_selector_t*, + private_traffic_selector_t *this, traffic_selector_t *other_public) { + private_traffic_selector_t *other, *subset; + u_int16_t from_port, to_port; + u_char *from, *to; + u_int8_t protocol; + size_t size; + + other = (private_traffic_selector_t*)other_public; + if (this->dynamic || other->dynamic) { /* no set_address() applied, TS has no subset */ return NULL; } - if (this->type == other->type && (this->protocol == other->protocol || - this->protocol == 0 || other->protocol == 0)) + + if (this->type != other->type) + { + return NULL; + } + switch (this->type) + { + case TS_IPV4_ADDR_RANGE: + size = sizeof(this->from4); + break; + case TS_IPV6_ADDR_RANGE: + size = sizeof(this->from6); + break; + default: + return NULL; + } + + if (this->protocol != other->protocol && + this->protocol != 0 && other->protocol != 0) { - u_int16_t from_port, to_port; - u_char *from, *to; - u_int8_t protocol; - size_t size; - private_traffic_selector_t *new_ts; + return NULL; + } + /* select protocol, which is not zero */ + protocol = max(this->protocol, other->protocol); + if ((is_opaque(this) && is_opaque(other)) || + (is_opaque(this) && is_any(other)) || + (is_opaque(other) && is_any(this))) + { + from_port = 0xffff; + to_port = 0; + } + else + { /* calculate the maximum port range allowed for both */ from_port = max(this->from_port, other->from_port); to_port = min(this->to_port, other->to_port); @@ -330,60 +384,46 @@ static traffic_selector_t *get_subset(private_traffic_selector_t *this, private_ { return NULL; } - /* select protocol, which is not zero */ - protocol = max(this->protocol, other->protocol); - - switch (this->type) - { - case TS_IPV4_ADDR_RANGE: - size = sizeof(this->from4); - break; - case TS_IPV6_ADDR_RANGE: - size = sizeof(this->from6); - break; - default: - return NULL; - } + } + /* get higher from-address */ + if (memcmp(this->from, other->from, size) > 0) + { + from = this->from; + } + else + { + from = other->from; + } + /* get lower to-address */ + if (memcmp(this->to, other->to, size) > 0) + { + to = other->to; + } + else + { + to = this->to; + } + /* if "from" > "to", we don't have a match */ + if (memcmp(from, to, size) > 0) + { + return NULL; + } - /* get higher from-address */ - if (memcmp(this->from, other->from, size) > 0) - { - from = this->from; - } - else - { - from = other->from; - } - /* get lower to-address */ - if (memcmp(this->to, other->to, size) > 0) - { - to = other->to; - } - else - { - to = this->to; - } - /* if "from" > "to", we don't have a match */ - if (memcmp(from, to, size) > 0) - { - return NULL; - } + /* we have a match in protocol, port, and address: return it... */ + subset = traffic_selector_create(protocol, this->type, from_port, to_port); + memcpy(subset->from, from, size); + memcpy(subset->to, to, size); + calc_netbits(subset); - /* we have a match in protocol, port, and address: return it... */ - new_ts = traffic_selector_create(protocol, this->type, from_port, to_port); - memcpy(new_ts->from, from, size); - memcpy(new_ts->to, to, size); - calc_netbits(new_ts); - return &new_ts->public; - } - return NULL; + return &subset->public; } -/** - * Implements traffic_selector_t.equals - */ -static bool equals(private_traffic_selector_t *this, private_traffic_selector_t *other) +METHOD(traffic_selector_t, equals, bool, + private_traffic_selector_t *this, traffic_selector_t *other_public) { + private_traffic_selector_t *other; + + other = (private_traffic_selector_t*)other_public; if (this->type != other->type) { return FALSE; @@ -535,11 +575,8 @@ METHOD(traffic_selector_t, set_address, void, } } -/** - * Implements traffic_selector_t.is_contained_in. - */ -static bool is_contained_in(private_traffic_selector_t *this, - private_traffic_selector_t *other) +METHOD(traffic_selector_t, is_contained_in, bool, + private_traffic_selector_t *this, traffic_selector_t *other) { private_traffic_selector_t *subset; bool contained_in = FALSE; @@ -548,7 +585,7 @@ static bool is_contained_in(private_traffic_selector_t *this, if (subset) { - if (equals(subset, this)) + if (equals(subset, &this->public)) { contained_in = TRUE; } @@ -739,12 +776,13 @@ traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type, * see header */ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, - u_int8_t netbits, u_int8_t protocol, u_int16_t port) + u_int8_t netbits, u_int8_t protocol, + u_int16_t from_port, u_int16_t to_port) { private_traffic_selector_t *this; chunk_t from; - this = traffic_selector_create(protocol, 0, 0, 65535); + this = traffic_selector_create(protocol, 0, from_port, to_port); switch (net->get_family(net)) { @@ -763,11 +801,6 @@ traffic_selector_t *traffic_selector_create_from_subnet(host_t *net, memcpy(this->from, from.ptr, from.len); netbits = min(netbits, this->type == TS_IPV4_ADDR_RANGE ? 32 : 128); calc_range(this, netbits); - if (port) - { - this->from_port = port; - this->to_port = port; - } net->destroy(net); return &this->public; @@ -818,8 +851,9 @@ traffic_selector_t *traffic_selector_create_from_string( /* * see header */ -traffic_selector_t *traffic_selector_create_from_cidr(char *string, - u_int8_t protocol, u_int16_t port) +traffic_selector_t *traffic_selector_create_from_cidr( + char *string, u_int8_t protocol, + u_int16_t from_port, u_int16_t to_port) { host_t *net; int bits; @@ -827,7 +861,8 @@ traffic_selector_t *traffic_selector_create_from_cidr(char *string, net = host_create_from_subnet(string, &bits); if (net) { - return traffic_selector_create_from_subnet(net, bits, protocol, port); + return traffic_selector_create_from_subnet(net, bits, protocol, + from_port, to_port); } return NULL; } @@ -859,8 +894,8 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, INIT(this, .public = { - .get_subset = (traffic_selector_t*(*)(traffic_selector_t*,traffic_selector_t*))get_subset, - .equals = (bool(*)(traffic_selector_t*,traffic_selector_t*))equals, + .get_subset = _get_subset, + .equals = _equals, .get_from_address = _get_from_address, .get_to_address = _get_to_address, .get_from_port = _get_from_port, @@ -869,7 +904,7 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, .get_protocol = _get_protocol, .is_host = _is_host, .is_dynamic = _is_dynamic, - .is_contained_in = (bool(*)(traffic_selector_t*,traffic_selector_t*))is_contained_in, + .is_contained_in = _is_contained_in, .includes = _includes, .set_address = _set_address, .to_subnet = _to_subnet, @@ -884,4 +919,3 @@ static private_traffic_selector_t *traffic_selector_create(u_int8_t protocol, return this; } - diff --git a/src/libstrongswan/selectors/traffic_selector.h b/src/libstrongswan/selectors/traffic_selector.h index b6da391aa..0de358b99 100644 --- a/src/libstrongswan/selectors/traffic_selector.h +++ b/src/libstrongswan/selectors/traffic_selector.h @@ -238,11 +238,13 @@ traffic_selector_t *traffic_selector_create_from_string( * * @param string CIDR string, such as 10.1.0.0/16 * @param protocol protocol for this ts, such as TCP or UDP - * @param port single port for this TS, 0 for any port + * @param from_port start of allowed port range + * @param to_port end of port range * @return traffic selector, NULL if string invalid */ -traffic_selector_t *traffic_selector_create_from_cidr(char *string, - u_int8_t protocol, u_int16_t port); +traffic_selector_t *traffic_selector_create_from_cidr( + char *string, u_int8_t protocol, + u_int16_t from_port, u_int16_t to_port); /** * Create a new traffic selector using data read from the net. @@ -288,14 +290,15 @@ traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type, * @param net subnet to use * @param netbits size of the subnet, as used in e.g. 192.168.0.0/24 notation * @param protocol protocol for this ts, such as TCP or UDP - * @param port port number, host order + * @param from_port start of allowed port range + * @param to_port end of port range * @return * - traffic_selector_t object * - NULL if address family of net not supported */ traffic_selector_t *traffic_selector_create_from_subnet( - host_t *net, u_int8_t netbits, - u_int8_t protocol, u_int16_t port); + host_t *net, u_int8_t netbits, u_int8_t protocol, + u_int16_t from_port, u_int16_t to_port); /** * Create a traffic selector for host-to-host cases. diff --git a/src/libstrongswan/threading/thread.c b/src/libstrongswan/threading/thread.c index e524409c7..d6d98d1ef 100644 --- a/src/libstrongswan/threading/thread.c +++ b/src/libstrongswan/threading/thread.c @@ -129,7 +129,11 @@ static thread_value_t *current_thread; #ifndef HAVE_PTHREAD_CANCEL /* if pthread_cancel is not available, we emulate it using a signal */ +#ifdef ANDROID +#define SIG_CANCEL SIGUSR2 +#else #define SIG_CANCEL (SIGRTMIN+7) +#endif /* the signal handler for SIG_CANCEL uses pthread_exit to terminate the * "cancelled" thread */ diff --git a/src/libstrongswan/utils/backtrace.c b/src/libstrongswan/utils/backtrace.c index 0b6683233..77137f9f1 100644 --- a/src/libstrongswan/utils/backtrace.c +++ b/src/libstrongswan/utils/backtrace.c @@ -27,6 +27,8 @@ #include "backtrace.h" +#include <utils/debug.h> + typedef struct private_backtrace_t private_backtrace_t; /** @@ -50,7 +52,42 @@ struct private_backtrace_t { void *frames[]; }; +/** + * Write a format string with arguments to a FILE line, if it is NULL to DBG + */ +static void println(FILE *file, char *format, ...) +{ + char buf[512]; + va_list args; + + va_start(args, format); + if (file) + { + vfprintf(file, format, args); + fputs("\n", file); + } + else + { + vsnprintf(buf, sizeof(buf), format, args); + DBG1(DBG_LIB, "%s", buf); + } + va_end(args); +} + #ifdef HAVE_DLADDR + +/** + * Same as tty_escape_get(), but for a potentially NULL FILE* + */ +static char* esc(FILE *file, tty_escape_t escape) +{ + if (file) + { + return tty_escape_get(fileno(file), escape); + } + return ""; +} + #ifdef HAVE_BFD_H #include <bfd.h> @@ -158,6 +195,7 @@ static void find_addr(bfd *abfd, asection *section, bfd_find_data_t *data) bfd_vma vma; const char *source; const char *function; + char fbuf[512] = "", sbuf[512] = ""; u_int line; if (!data->found || (bfd_get_section_flags(abfd, section) & SEC_ALLOC) != 0) @@ -175,16 +213,18 @@ static void find_addr(bfd *abfd, asection *section, bfd_find_data_t *data) { if (source || function) { - fprintf(data->file, " -> "); if (function) { - fprintf(data->file, "\e[34m%s() ", function); + snprintf(fbuf, sizeof(fbuf), "%s%s() ", + esc(data->file, TTY_FG_BLUE), function); } if (source) { - fprintf(data->file, "\e[32m@ %s:%d", source, line); + snprintf(sbuf, sizeof(sbuf), "%s@ %s:%d", + esc(data->file, TTY_FG_GREEN), source, line); } - fprintf(data->file, "\e[0m\n"); + println(data->file, " -> %s%s%s", fbuf, sbuf, + esc(data->file, TTY_FG_DEF)); } } } @@ -296,26 +336,28 @@ void backtrace_deinit() {} */ static void print_sourceline(FILE *file, char *filename, void *ptr) { - char cmd[1024]; + char buf[1024]; FILE *output; - int c; + int c, i = 0; - snprintf(cmd, sizeof(cmd), "addr2line -e %s %p", filename, ptr); - output = popen(cmd, "r"); + snprintf(buf, sizeof(buf), "addr2line -e %s %p", filename, ptr); + output = popen(buf, "r"); if (output) { - fprintf(file, " -> \e[32m"); - while (TRUE) + while (i < sizeof(buf)) { c = getc(output); if (c == '\n' || c == EOF) { + buf[i++] = 0; break; } - fputc(c, file); + buf[i++] = c; } pclose(output); - fprintf(file, "\e[0m\n"); + + println(file, " -> %s%s%s", esc(file, TTY_FG_GREEN), buf, + esc(file, TTY_FG_DEF)); } } @@ -337,7 +379,7 @@ METHOD(backtrace_t, log_, void, strings = backtrace_symbols(this->frames, this->frame_count); - fprintf(file, " dumping %d stack frame addresses:\n", this->frame_count); + println(file, " dumping %d stack frame addresses:", this->frame_count); for (i = 0; i < this->frame_count; i++) { #ifdef HAVE_DLADDR @@ -353,16 +395,20 @@ METHOD(backtrace_t, log_, void, } if (info.dli_sname) { - fprintf(file, " \e[33m%s\e[0m @ %p (\e[31m%s\e[0m+0x%tx) [%p]\n", - info.dli_fname, info.dli_fbase, info.dli_sname, - this->frames[i] - info.dli_saddr, this->frames[i]); + println(file, " %s%s%s @ %p (%s%s%s+0x%tx) [%p]", + esc(file, TTY_FG_YELLOW), info.dli_fname, + esc(file, TTY_FG_DEF), info.dli_fbase, + esc(file, TTY_FG_RED), info.dli_sname, + esc(file, TTY_FG_DEF), this->frames[i] - info.dli_saddr, + this->frames[i]); } else { - fprintf(file, " \e[33m%s\e[0m @ %p [%p]\n", info.dli_fname, - info.dli_fbase, this->frames[i]); + println(file, " %s%s%s @ %p [%p]", + esc(file, TTY_FG_YELLOW), info.dli_fname, + esc(file, TTY_FG_DEF), info.dli_fbase, this->frames[i]); } - if (detailed) + if (detailed && info.dli_fname[0]) { print_sourceline(file, (char*)info.dli_fname, ptr); } @@ -370,12 +416,12 @@ METHOD(backtrace_t, log_, void, else #endif /* HAVE_DLADDR */ { - fprintf(file, " %s\n", strings[i]); + println(file, " %s", strings[i]); } } free (strings); #else /* !HAVE_BACKTRACE */ - fprintf(file, "C library does not support backtrace().\n"); + println(file, "C library does not support backtrace()."); #endif /* HAVE_BACKTRACE */ } @@ -511,9 +557,8 @@ void backtrace_dump(char *label, FILE *file, bool detailed) if (label) { - fprintf(file, "Debug backtrace: %s\n", label); + println(file, "Debug backtrace: %s", label); } backtrace->log(backtrace, file, detailed); backtrace->destroy(backtrace); } - diff --git a/src/libstrongswan/utils/backtrace.h b/src/libstrongswan/utils/backtrace.h index aeeba4dd6..62104238d 100644 --- a/src/libstrongswan/utils/backtrace.h +++ b/src/libstrongswan/utils/backtrace.h @@ -35,7 +35,10 @@ struct backtrace_t { /** * Log the backtrace to a FILE stream. * - * @param file FILE to log backtrace to + * If no file pointer is given, the backtrace is reported over the debug + * framework to the registered dbg() callback function. + * + * @param file FILE to log backtrace to, NULL for dbg() function * @param detailed TRUE to resolve line/file using addr2line (slow) */ void (*log)(backtrace_t *this, FILE *file, bool detailed); @@ -81,7 +84,7 @@ backtrace_t *backtrace_create(int skip); * Create a backtrace, dump it and clean it up. * * @param label description to print for this backtrace, or NULL - * @param file FILE to log backtrace to + * @param file FILE to log backtrace to, NULL to dbg() function * @param detailed TRUE to resolve line/file using addr2line (slow) */ void backtrace_dump(char *label, FILE *file, bool detailed); diff --git a/src/libstrongswan/utils/capabilities.c b/src/libstrongswan/utils/capabilities.c index c36a76efe..44a14496c 100644 --- a/src/libstrongswan/utils/capabilities.c +++ b/src/libstrongswan/utils/capabilities.c @@ -29,7 +29,9 @@ #include <utils/debug.h> -#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETGRNAM_R) +#if !defined(HAVE_GETPWNAM_R) || \ + !defined(HAVE_GETGRNAM_R) || \ + !defined(HAVE_GETPWUID_R) # include <threading/mutex.h> # define EMULATE_R_FUNCS #endif @@ -188,6 +190,34 @@ METHOD(capabilities_t, resolve_gid, bool, return FALSE; } +/** + * Initialize supplementary groups for unprivileged user + */ +static bool init_supplementary_groups(private_capabilities_t *this) +{ + struct passwd *pwp; + int res = -1; + +#ifdef HAVE_GETPWUID_R + struct passwd pwd; + char buf[1024]; + + if (getpwuid_r(this->uid, &pwd, buf, sizeof(buf), &pwp) == 0 && pwp) + { + res = initgroups(pwp->pw_name, this->gid); + } +#else /* HAVE_GETPWUID_R */ + this->mutex->lock(this->mutex); + pwp = getpwuid(this->uid); + if (pwp) + { + res = initgroups(pwp->pw_name, this->gid); + } + this->mutex->unlock(this->mutex); +#endif /* HAVE_GETPWUID_R */ + return res == 0; +} + METHOD(capabilities_t, drop, bool, private_capabilities_t *this) { @@ -195,6 +225,12 @@ METHOD(capabilities_t, drop, bool, prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); #endif + if (!init_supplementary_groups(this)) + { + DBG1(DBG_LIB, "initializing supplementary groups for %u failed", + this->uid); + return FALSE; + } if (this->gid && setgid(this->gid) != 0) { DBG1(DBG_LIB, "change to unprivileged group %u failed: %s", diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h index 67848eec1..bc14b7394 100644 --- a/src/libstrongswan/utils/chunk.h +++ b/src/libstrongswan/utils/chunk.h @@ -191,6 +191,11 @@ static inline void chunk_clear(chunk_t *chunk) #define chunk_from_thing(thing) chunk_create((char*)&(thing), sizeof(thing)) /** + * Initialize a chunk from a static string, not containing 0-terminator + */ +#define chunk_from_str(str) chunk_create(str, strlen(str)) + +/** * Allocate a chunk on the heap */ #define chunk_alloc(bytes) ({size_t x = (bytes); chunk_create(x ? malloc(x) : NULL, x);}) diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c index 2669c2da6..4176320dc 100644 --- a/src/libstrongswan/utils/identification.c +++ b/src/libstrongswan/utils/identification.c @@ -49,10 +49,10 @@ ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID, "ID_DER_ASN1_DN", "ID_DER_ASN1_GN", "ID_KEY_ID"); -ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_MYID, ID_KEY_ID, +ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_USER_ID, ID_KEY_ID, "ID_DER_ASN1_GN_URI", - "ID_MYID"); -ENUM_END(id_type_names, ID_MYID); + "ID_USER_ID"); +ENUM_END(id_type_names, ID_USER_ID); /** * coding of X.501 distinguished name @@ -790,6 +790,7 @@ int identification_printf_hook(printf_hook_data_t *data, case ID_FQDN: case ID_RFC822_ADDR: case ID_DER_ASN1_GN_URI: + case ID_USER_ID: chunk_printable(this->encoded, &proper, '?'); snprintf(buf, sizeof(buf), "%.*s", (int)proper.len, proper.ptr); chunk_free(&proper); @@ -812,9 +813,6 @@ int identification_printf_hook(printf_hook_data_t *data, snprintf(buf, sizeof(buf), "%#B", &this->encoded); } break; - case ID_MYID: - snprintf(buf, sizeof(buf), "%%myid"); - break; default: snprintf(buf, sizeof(buf), "(unknown ID type: %d)", this->type); break; @@ -873,6 +871,7 @@ static private_identification_t *identification_create(id_type_t type) break; case ID_FQDN: case ID_RFC822_ADDR: + case ID_USER_ID: this->public.matches = _matches_string; this->public.equals = _equals_strcasecmp; this->public.contains_wildcards = _contains_wildcards_memchr; @@ -1023,9 +1022,16 @@ identification_t * identification_create_from_data(chunk_t data) { char buf[data.len + 1]; - /* use string constructor */ - snprintf(buf, sizeof(buf), "%.*s", (int)data.len, data.ptr); - return identification_create_from_string(buf); + if (is_asn1(data)) + { + return identification_create_from_encoding(ID_DER_ASN1_DN, data); + } + else + { + /* use string constructor */ + snprintf(buf, sizeof(buf), "%.*s", (int)data.len, data.ptr); + return identification_create_from_string(buf); + } } /* diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h index cdf229127..00d740765 100644 --- a/src/libstrongswan/utils/identification.h +++ b/src/libstrongswan/utils/identification.h @@ -126,14 +126,14 @@ enum id_type_t { ID_KEY_ID = 11, /** - * private type which represents a GeneralName of type URI + * Private ID type which represents a GeneralName of type URI */ ID_DER_ASN1_GN_URI = 201, /** - * Private ID used by the pluto daemon for opportunistic encryption + * Private ID type which represents a user ID */ - ID_MYID = 203, + ID_USER_ID = 202 }; /** diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index 2b0be1661..6bf4d63cd 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -226,6 +226,8 @@ char *whitelist[] = { "setpwent", "endpwent", "getspnam_r", + "getpwuid_r", + "initgroups", /* ignore dlopen, as we do not dlclose to get proper leak reports */ "dlopen", "dlerror", diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c index bf0224c5f..2f38d8a93 100644 --- a/src/libstrongswan/utils/utils.c +++ b/src/libstrongswan/utils/utils.c @@ -194,6 +194,69 @@ bool mkdir_p(const char *path, mode_t mode) return TRUE; } +ENUM(tty_color_names, TTY_RESET, TTY_BG_DEF, + "\e[0m", + "\e[1m", + "\e[4m", + "\e[5m", + "\e[30m", + "\e[31m", + "\e[32m", + "\e[33m", + "\e[34m", + "\e[35m", + "\e[36m", + "\e[37m", + "\e[39m", + "\e[40m", + "\e[41m", + "\e[42m", + "\e[43m", + "\e[44m", + "\e[45m", + "\e[46m", + "\e[47m", + "\e[49m", +); + +/** + * Get the escape string for a given TTY color, empty string on non-tty FILE + */ +char* tty_escape_get(int fd, tty_escape_t escape) +{ + if (!isatty(fd)) + { + return ""; + } + switch (escape) + { + case TTY_RESET: + case TTY_BOLD: + case TTY_UNDERLINE: + case TTY_BLINKING: + case TTY_FG_BLACK: + case TTY_FG_RED: + case TTY_FG_GREEN: + case TTY_FG_YELLOW: + case TTY_FG_BLUE: + case TTY_FG_MAGENTA: + case TTY_FG_CYAN: + case TTY_FG_WHITE: + case TTY_FG_DEF: + case TTY_BG_BLACK: + case TTY_BG_RED: + case TTY_BG_GREEN: + case TTY_BG_YELLOW: + case TTY_BG_BLUE: + case TTY_BG_MAGENTA: + case TTY_BG_CYAN: + case TTY_BG_WHITE: + case TTY_BG_DEF: + return enum_to_name(tty_color_names, escape); + /* warn if a excape code is missing */ + } + return ""; +} /** * The size of the thread-specific error buffer @@ -387,6 +450,14 @@ status_t return_failed() } /** + * returns SUCCESS + */ +status_t return_success() +{ + return SUCCESS; +} + +/** * nop operation */ void nop() @@ -460,7 +531,7 @@ int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec, bool utc = *((bool*)(args[1]));; struct tm t; - if (time == UNDEFINED_TIME) + if (*time == UNDEFINED_TIME) { return print_in_hook(data, "--- -- --:--:--%s----", utc ? " UTC " : " "); diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h index 7b1beb93a..c66c665e0 100644 --- a/src/libstrongswan/utils/utils.h +++ b/src/libstrongswan/utils/utils.h @@ -314,6 +314,46 @@ enum status_t { */ extern enum_name_t *status_names; +typedef enum tty_escape_t tty_escape_t; + +/** + * Excape codes for tty colors + */ +enum tty_escape_t { + /** text properties */ + TTY_RESET, + TTY_BOLD, + TTY_UNDERLINE, + TTY_BLINKING, + + /** foreground colors */ + TTY_FG_BLACK, + TTY_FG_RED, + TTY_FG_GREEN, + TTY_FG_YELLOW, + TTY_FG_BLUE, + TTY_FG_MAGENTA, + TTY_FG_CYAN, + TTY_FG_WHITE, + TTY_FG_DEF, + + /** background colors */ + TTY_BG_BLACK, + TTY_BG_RED, + TTY_BG_GREEN, + TTY_BG_YELLOW, + TTY_BG_BLUE, + TTY_BG_MAGENTA, + TTY_BG_CYAN, + TTY_BG_WHITE, + TTY_BG_DEF, +}; + +/** + * Get the escape string for a given TTY color, empty string on non-tty fd + */ +char* tty_escape_get(int fd, tty_escape_t escape); + /** * deprecated pluto style return value: * error message, NULL for success @@ -496,6 +536,11 @@ bool return_false(); status_t return_failed(); /** + * returns SUCCESS + */ +status_t return_success(); + +/** * Write a 16-bit host order value in network order to an unaligned address. * * @param host host order 16-bit value diff --git a/src/libtls/tls.c b/src/libtls/tls.c index dea08e3eb..6d33d843d 100644 --- a/src/libtls/tls.c +++ b/src/libtls/tls.c @@ -107,16 +107,6 @@ struct private_tls_t { bool is_server; /** - * Server identity - */ - identification_t *server; - - /** - * Peer identity - */ - identification_t *peer; - - /** * Negotiated TLS version */ tls_version_t version; @@ -359,6 +349,18 @@ METHOD(tls_t, is_server, bool, return this->is_server; } +METHOD(tls_t, get_server_id, identification_t*, + private_tls_t *this) +{ + return this->handshake->get_server_id(this->handshake); +} + +METHOD(tls_t, get_peer_id, identification_t*, + private_tls_t *this) +{ + return this->handshake->get_peer_id(this->handshake); +} + METHOD(tls_t, get_version, tls_version_t, private_tls_t *this) { @@ -421,8 +423,6 @@ METHOD(tls_t, destroy, void, this->fragmentation->destroy(this->fragmentation); this->crypto->destroy(this->crypto); this->handshake->destroy(this->handshake); - DESTROY_IF(this->peer); - this->server->destroy(this->server); DESTROY_IF(this->application); this->alert->destroy(this->alert); @@ -457,6 +457,8 @@ tls_t *tls_create(bool is_server, identification_t *server, .process = _process, .build = _build, .is_server = _is_server, + .get_server_id = _get_server_id, + .get_peer_id = _get_peer_id, .get_version = _get_version, .set_version = _set_version, .get_purpose = _get_purpose, @@ -466,8 +468,6 @@ tls_t *tls_create(bool is_server, identification_t *server, }, .is_server = is_server, .version = TLS_1_2, - .server = server->clone(server), - .peer = peer ? peer->clone(peer) : NULL, .application = application, .purpose = purpose, ); @@ -477,12 +477,12 @@ tls_t *tls_create(bool is_server, identification_t *server, if (is_server) { this->handshake = &tls_server_create(&this->public, this->crypto, - this->alert, this->server, this->peer)->handshake; + this->alert, server, peer)->handshake; } else { this->handshake = &tls_peer_create(&this->public, this->crypto, - this->alert, this->peer, this->server)->handshake; + this->alert, peer, server)->handshake; } this->fragmentation = tls_fragmentation_create(this->handshake, this->alert, this->application); diff --git a/src/libtls/tls.h b/src/libtls/tls.h index 6b4876f73..7f45b1e09 100644 --- a/src/libtls/tls.h +++ b/src/libtls/tls.h @@ -193,6 +193,20 @@ struct tls_t { bool (*is_server)(tls_t *this); /** + * Return the server identity. + * + * @return server identity + */ + identification_t* (*get_server_id)(tls_t *this); + + /** + * Return the peer identity. + * + * @return peer identity + */ + identification_t* (*get_peer_id)(tls_t *this); + + /** * Get the negotiated TLS/SSL version. * * @return negotiated TLS version diff --git a/src/libtls/tls_fragmentation.c b/src/libtls/tls_fragmentation.c index c76376b43..6e4347e3c 100644 --- a/src/libtls/tls_fragmentation.c +++ b/src/libtls/tls_fragmentation.c @@ -223,7 +223,7 @@ static status_t process_application(private_tls_fragmentation_t *this, continue; case SUCCESS: this->application_finished = TRUE; - return SUCCESS; + /* FALL */ case FAILED: default: this->alert->add(this->alert, TLS_FATAL, TLS_CLOSE_NOTIFY); @@ -368,7 +368,7 @@ static status_t build_application(private_tls_fragmentation_t *this) break; case SUCCESS: this->application_finished = TRUE; - break; + /* FALL */ case FAILED: default: this->alert->add(this->alert, TLS_FATAL, TLS_CLOSE_NOTIFY); @@ -391,6 +391,10 @@ METHOD(tls_fragmentation_t, build, status_t, this->state = ALERT_SENT; return INVALID_STATE; case ALERT_SENT: + if (this->application_finished) + { + return SUCCESS; + } return FAILED; case ALERT_NONE: break; diff --git a/src/libtls/tls_handshake.h b/src/libtls/tls_handshake.h index bea0024eb..7fa660c58 100644 --- a/src/libtls/tls_handshake.h +++ b/src/libtls/tls_handshake.h @@ -84,6 +84,20 @@ struct tls_handshake_t { bool (*finished)(tls_handshake_t *this); /** + * Get the peer identity authenticated/to authenticate during handshake. + * + * @return peer identity + */ + identification_t* (*get_peer_id)(tls_handshake_t *this); + + /** + * Get the server identity authenticated/to authenticate during handshake. + * + * @return server identity + */ + identification_t* (*get_server_id)(tls_handshake_t *this); + + /** * Destroy a tls_handshake_t. */ void (*destroy)(tls_handshake_t *this); diff --git a/src/libtls/tls_peer.c b/src/libtls/tls_peer.c index 622df4035..b429da300 100644 --- a/src/libtls/tls_peer.c +++ b/src/libtls/tls_peer.c @@ -665,6 +665,8 @@ METHOD(tls_handshake_t, process, status_t, { return process_certreq(this, reader); } + /* no cert request, server does not want to authenticate us */ + DESTROY_IF(this->peer); this->peer = NULL; /* fall through since TLS_CERTIFICATE_REQUEST is optional */ case STATE_CERTREQ_RECEIVED: @@ -850,6 +852,7 @@ static status_t send_certificate(private_tls_peer_t *this, { DBG1(DBG_TLS, "no TLS peer certificate found for '%Y', " "skipping client authentication", this->peer); + this->peer->destroy(this->peer); this->peer = NULL; } @@ -1132,11 +1135,25 @@ METHOD(tls_handshake_t, finished, bool, return this->state == STATE_FINISHED_RECEIVED; } +METHOD(tls_handshake_t, get_peer_id, identification_t*, + private_tls_peer_t *this) +{ + return this->peer; +} + +METHOD(tls_handshake_t, get_server_id, identification_t*, + private_tls_peer_t *this) +{ + return this->server; +} + METHOD(tls_handshake_t, destroy, void, private_tls_peer_t *this) { DESTROY_IF(this->private); DESTROY_IF(this->dh); + DESTROY_IF(this->peer); + this->server->destroy(this->server); this->peer_auth->destroy(this->peer_auth); this->server_auth->destroy(this->server_auth); free(this->hashsig.ptr); @@ -1161,6 +1178,8 @@ tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert .cipherspec_changed = _cipherspec_changed, .change_cipherspec = _change_cipherspec, .finished = _finished, + .get_peer_id = _get_peer_id, + .get_server_id = _get_server_id, .destroy = _destroy, }, }, @@ -1168,8 +1187,8 @@ tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert .tls = tls, .crypto = crypto, .alert = alert, - .peer = peer, - .server = server, + .peer = peer ? peer->clone(peer) : NULL, + .server = server->clone(server), .peer_auth = auth_cfg_create(), .server_auth = auth_cfg_create(), ); diff --git a/src/libtls/tls_peer.h b/src/libtls/tls_peer.h index f773ea72e..e4ff6f83c 100644 --- a/src/libtls/tls_peer.h +++ b/src/libtls/tls_peer.h @@ -41,11 +41,15 @@ struct tls_peer_t { /** * Create a tls_peer instance. -* + * + * If a peer identity is given, but the client does not get requested or is + * otherwise unable to perform client authentication, NULL is returned in + * tls_handshake_t.get_peer_id() instead of the peer identity. + * * @param tls TLS stack * @param crypto TLS crypto helper * @param alert TLS alert handler - * @param peer peer identity + * @param peer peer identity, NULL to skip client authentication * @param server server identity */ tls_peer_t *tls_peer_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert, diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c index ec42b67fc..aeb5a714f 100644 --- a/src/libtls/tls_server.c +++ b/src/libtls/tls_server.c @@ -80,6 +80,11 @@ struct private_tls_server_t { identification_t *peer; /** + * Is it acceptable if we couldn't verify the peer certificate? + */ + bool peer_auth_optional; + + /** * State we are in */ server_state_t state; @@ -367,6 +372,12 @@ static status_t process_certificate(private_tls_server_t *this, DBG1(DBG_TLS, "received TLS peer certificate '%Y'", cert->get_subject(cert)); first = FALSE; + if (this->peer == NULL) + { /* apply identity to authenticate */ + this->peer = cert->get_subject(cert); + this->peer = this->peer->clone(this->peer); + this->peer_auth_optional = TRUE; + } } else { @@ -550,13 +561,22 @@ static status_t process_cert_verify(private_tls_server_t *this, { DBG1(DBG_TLS, "no trusted certificate found for '%Y' to verify TLS peer", this->peer); - this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN); - return NEED_MORE; + if (!this->peer_auth_optional) + { /* client authentication is required */ + this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN); + return NEED_MORE; + } + /* reset peer identity, we couldn't authenticate it */ + this->peer->destroy(this->peer); + this->peer = NULL; + this->state = STATE_KEY_EXCHANGE_RECEIVED; + } + else + { + this->state = STATE_CERT_VERIFY_RECEIVED; } - this->crypto->append_handshake(this->crypto, TLS_CERTIFICATE_VERIFY, reader->peek(reader)); - this->state = STATE_CERT_VERIFY_RECEIVED; return NEED_MORE; } @@ -979,11 +999,7 @@ METHOD(tls_handshake_t, build, status_t, } /* otherwise fall through to next state */ case STATE_KEY_EXCHANGE_SENT: - if (this->peer) - { - return send_certificate_request(this, type, writer); - } - /* otherwise fall through to next state */ + return send_certificate_request(this, type, writer); case STATE_CERTREQ_SENT: return send_hello_done(this, type, writer); case STATE_CIPHERSPEC_CHANGED_OUT: @@ -1045,11 +1061,25 @@ METHOD(tls_handshake_t, finished, bool, return this->state == STATE_FINISHED_SENT; } +METHOD(tls_handshake_t, get_peer_id, identification_t*, + private_tls_server_t *this) +{ + return this->peer; +} + +METHOD(tls_handshake_t, get_server_id, identification_t*, + private_tls_server_t *this) +{ + return this->server; +} + METHOD(tls_handshake_t, destroy, void, private_tls_server_t *this) { DESTROY_IF(this->private); DESTROY_IF(this->dh); + DESTROY_IF(this->peer); + this->server->destroy(this->server); this->peer_auth->destroy(this->peer_auth); this->server_auth->destroy(this->server_auth); free(this->hashsig.ptr); @@ -1075,14 +1105,16 @@ tls_server_t *tls_server_create(tls_t *tls, .cipherspec_changed = _cipherspec_changed, .change_cipherspec = _change_cipherspec, .finished = _finished, + .get_peer_id = _get_peer_id, + .get_server_id = _get_server_id, .destroy = _destroy, }, }, .tls = tls, .crypto = crypto, .alert = alert, - .server = server, - .peer = peer, + .server = server->clone(server), + .peer = peer ? peer->clone(peer) : NULL, .state = STATE_INIT, .peer_auth = auth_cfg_create(), .server_auth = auth_cfg_create(), diff --git a/src/libtls/tls_server.h b/src/libtls/tls_server.h index 6289dc8eb..d6b8de153 100644 --- a/src/libtls/tls_server.h +++ b/src/libtls/tls_server.h @@ -42,11 +42,16 @@ struct tls_server_t { /** * Create a tls_server instance. * + * If a peer identity is given, the client must authenticate with a valid + * certificate for this identity, or the connection fails. If peer is NULL, + * but the client authenticates nonetheless, the authenticated identity + * gets returned by tls_handshake_t.get_peer_id(). + * * @param tls TLS stack * @param crypto TLS crypto helper * @param alert TLS alert handler * @param server server identity - * @param peer peer identity + * @param peer peer identity, or NULL */ tls_server_t *tls_server_create(tls_t *tls, tls_crypto_t *crypto, tls_alert_t *alert, diff --git a/src/libtls/tls_socket.c b/src/libtls/tls_socket.c index 75b714e30..58b511809 100644 --- a/src/libtls/tls_socket.c +++ b/src/libtls/tls_socket.c @@ -42,14 +42,39 @@ struct private_tls_application_t { tls_application_t application; /** - * Chunk of data to send + * Output buffer to write to */ chunk_t out; /** - * Chunk of data received + * Number of bytes written to out + */ + size_t out_done; + + /** + * Input buffer to read to */ chunk_t in; + + /** + * Number of bytes read to in + */ + size_t in_done; + + /** + * Cached input data + */ + chunk_t cache; + + /** + * Bytes cosnumed in cache + */ + size_t cache_done; + + /** + * Close TLS connection? + */ + bool close; }; /** @@ -82,22 +107,44 @@ METHOD(tls_application_t, process, status_t, private_tls_application_t *this, bio_reader_t *reader) { chunk_t data; + size_t len; - if (!reader->read_data(reader, reader->remaining(reader), &data)) + if (this->close) { - return FAILED; + return SUCCESS; + } + len = min(reader->remaining(reader), this->in.len - this->in_done); + if (len) + { /* copy to read buffer as much as fits in */ + if (!reader->read_data(reader, len, &data)) + { + return FAILED; + } + memcpy(this->in.ptr + this->in_done, data.ptr, data.len); + this->in_done += data.len; + } + else + { /* read buffer is full, cache for next read */ + if (!reader->read_data(reader, reader->remaining(reader), &data)) + { + return FAILED; + } + this->cache = chunk_cat("mc", this->cache, data); } - this->in = chunk_cat("mc", this->in, data); return NEED_MORE; } METHOD(tls_application_t, build, status_t, private_tls_application_t *this, bio_writer_t *writer) { - if (this->out.len) + if (this->close) + { + return SUCCESS; + } + if (this->out.len > this->out_done) { writer->write_data(writer, this->out); - this->out = chunk_empty; + this->out_done = this->out.len; return NEED_MORE; } return INVALID_STATE; @@ -106,11 +153,11 @@ METHOD(tls_application_t, build, status_t, /** * TLS data exchange loop */ -static bool exchange(private_tls_socket_t *this, bool wr) +static bool exchange(private_tls_socket_t *this, bool wr, bool block) { char buf[CRYPTO_BUF_SIZE], *pos; ssize_t len, out; - int round = 0; + int round = 0, flags; for (round = 0; TRUE; round++) { @@ -137,6 +184,8 @@ static bool exchange(private_tls_socket_t *this, bool wr) continue; case INVALID_STATE: break; + case SUCCESS: + return TRUE; default: return FALSE; } @@ -144,55 +193,97 @@ static bool exchange(private_tls_socket_t *this, bool wr) } if (wr) { - if (this->app.out.len == 0) + if (this->app.out_done == this->app.out.len) { /* all data written */ return TRUE; } } else { - if (this->app.in.len) - { /* some data received */ + if (this->app.in_done == this->app.in.len) + { /* buffer fully received */ return TRUE; } - if (round > 0) - { /* did some handshaking, return empty chunk to not block */ - return TRUE; + } + + flags = 0; + if (this->app.out_done == this->app.out.len) + { + if (!block || this->app.in_done) + { + flags |= MSG_DONTWAIT; } } - len = read(this->fd, buf, sizeof(buf)); - if (len <= 0) + len = recv(this->fd, buf, sizeof(buf), flags); + if (len < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK) + { + if (this->app.in_done == 0) + { + /* reading, nothing got yet, and call would block */ + errno = EWOULDBLOCK; + this->app.in_done = -1; + } + return TRUE; + } return FALSE; } - if (this->tls->process(this->tls, buf, len) != NEED_MORE) + if (len == 0) + { /* EOF */ + return TRUE; + } + switch (this->tls->process(this->tls, buf, len)) { - return FALSE; + case NEED_MORE: + break; + case SUCCESS: + return TRUE; + default: + return FALSE; } } } -METHOD(tls_socket_t, read_, bool, - private_tls_socket_t *this, chunk_t *buf) +METHOD(tls_socket_t, read_, ssize_t, + private_tls_socket_t *this, void *buf, size_t len, bool block) { - if (exchange(this, FALSE)) + if (this->app.cache.len) { - *buf = this->app.in; - this->app.in = chunk_empty; - return TRUE; + size_t cache; + + cache = min(len, this->app.cache.len - this->app.cache_done); + memcpy(buf, this->app.cache.ptr + this->app.cache_done, cache); + + this->app.cache_done += cache; + if (this->app.cache_done == this->app.cache.len) + { + chunk_free(&this->app.cache); + this->app.cache_done = 0; + } + return cache; } - return FALSE; + this->app.in.ptr = buf; + this->app.in.len = len; + this->app.in_done = 0; + if (exchange(this, FALSE, block)) + { + return this->app.in_done; + } + return -1; } -METHOD(tls_socket_t, write_, bool, - private_tls_socket_t *this, chunk_t buf) +METHOD(tls_socket_t, write_, ssize_t, + private_tls_socket_t *this, void *buf, size_t len) { - this->app.out = buf; - if (exchange(this, TRUE)) + this->app.out.ptr = buf; + this->app.out.len = len; + this->app.out_done = 0; + if (exchange(this, TRUE, FALSE)) { - return TRUE; + return this->app.out_done; } - return FALSE; + return -1; } METHOD(tls_socket_t, splice, bool, @@ -200,68 +291,85 @@ METHOD(tls_socket_t, splice, bool, { char buf[PLAIN_BUF_SIZE], *pos; fd_set set; - chunk_t data; - ssize_t len; - bool old; + ssize_t in, out; + bool old, plain_eof = FALSE, crypto_eof = FALSE; - while (TRUE) + while (!plain_eof && !crypto_eof) { FD_ZERO(&set); FD_SET(rfd, &set); FD_SET(this->fd, &set); old = thread_cancelability(TRUE); - len = select(max(rfd, this->fd) + 1, &set, NULL, NULL, NULL); + in = select(max(rfd, this->fd) + 1, &set, NULL, NULL, NULL); thread_cancelability(old); - if (len == -1) + if (in == -1) { DBG1(DBG_TLS, "TLS select error: %s", strerror(errno)); return FALSE; } - if (FD_ISSET(this->fd, &set)) + while (!plain_eof && FD_ISSET(this->fd, &set)) { - if (!read_(this, &data)) - { - DBG2(DBG_TLS, "TLS read error/disconnect"); - return TRUE; - } - pos = data.ptr; - while (data.len) + in = read_(this, buf, sizeof(buf), FALSE); + switch (in) { - len = write(wfd, pos, data.len); - if (len == -1) - { - free(data.ptr); - DBG1(DBG_TLS, "TLS plain write error: %s", strerror(errno)); - return FALSE; - } - data.len -= len; - pos += len; + case 0: + plain_eof = TRUE; + break; + case -1: + if (errno != EWOULDBLOCK) + { + DBG1(DBG_TLS, "TLS read error: %s", strerror(errno)); + return FALSE; + } + break; + default: + pos = buf; + while (in) + { + out = write(wfd, pos, in); + if (out == -1) + { + DBG1(DBG_TLS, "TLS plain write error: %s", + strerror(errno)); + return FALSE; + } + in -= out; + pos += out; + } + continue; } - free(data.ptr); + break; } - if (FD_ISSET(rfd, &set)) + if (!crypto_eof && FD_ISSET(rfd, &set)) { - len = read(rfd, buf, sizeof(buf)); - if (len > 0) - { - if (!write_(this, chunk_create(buf, len))) - { - DBG1(DBG_TLS, "TLS write error"); - return FALSE; - } - } - else + in = read(rfd, buf, sizeof(buf)); + switch (in) { - if (len < 0) - { + case 0: + crypto_eof = TRUE; + break; + case -1: DBG1(DBG_TLS, "TLS plain read error: %s", strerror(errno)); return FALSE; - } - return TRUE; + default: + pos = buf; + while (in) + { + out = write_(this, pos, in); + if (out == -1) + { + DBG1(DBG_TLS, "TLS write error"); + return FALSE; + } + in -= out; + pos += out; + } + break; } } } + return TRUE; } METHOD(tls_socket_t, get_fd, int, @@ -270,11 +378,26 @@ METHOD(tls_socket_t, get_fd, int, return this->fd; } +METHOD(tls_socket_t, get_server_id, identification_t*, + private_tls_socket_t *this) +{ + return this->tls->get_server_id(this->tls); +} + +METHOD(tls_socket_t, get_peer_id, identification_t*, + private_tls_socket_t *this) +{ + return this->tls->get_peer_id(this->tls); +} + METHOD(tls_socket_t, destroy, void, private_tls_socket_t *this) { + /* send a TLS close notify if not done yet */ + this->app.close = TRUE; + write_(this, NULL, 0); + free(this->app.cache.ptr); this->tls->destroy(this->tls); - free(this->app.in.ptr); free(this); } @@ -292,6 +415,8 @@ tls_socket_t *tls_socket_create(bool is_server, identification_t *server, .write = _write_, .splice = _splice, .get_fd = _get_fd, + .get_server_id = _get_server_id, + .get_peer_id = _get_peer_id, .destroy = _destroy, }, .app = { diff --git a/src/libtls/tls_socket.h b/src/libtls/tls_socket.h index edd05fd29..75130a4d3 100644 --- a/src/libtls/tls_socket.h +++ b/src/libtls/tls_socket.h @@ -35,24 +35,27 @@ typedef struct tls_socket_t tls_socket_t; struct tls_socket_t { /** - * Read data from secured socket, return allocated chunk. + * Read data from secured socket. * * This call is blocking, you may use select() on the underlying socket to - * wait for data. If the there was non-application data available, the - * read function can return an empty chunk. + * wait for data. If "block" is FALSE and no application data is available, + * the function returns -1 and sets errno to EWOULDBLOCK. * - * @param data pointer to allocate received data - * @return TRUE if data received successfully + * @param buf buffer to write received data to + * @param len size of buffer + * @param block TRUE to block this call, FALSE to fail if it would block + * @return number of bytes read, 0 on EOF, -1 on error */ - bool (*read)(tls_socket_t *this, chunk_t *data); + ssize_t (*read)(tls_socket_t *this, void *buf, size_t len, bool block); /** - * Write a chunk of data over the secured socket. + * Write data over the secured socket. * - * @param data data to send - * @return TRUE if data sent successfully + * @param buf data to send + * @param len number of bytes to write from buf + * @return number of bytes written, -1 on error */ - bool (*write)(tls_socket_t *this, chunk_t data); + ssize_t (*write)(tls_socket_t *this, void *buf, size_t len); /** * Read/write plain data from file descriptor. @@ -74,6 +77,20 @@ struct tls_socket_t { int (*get_fd)(tls_socket_t *this); /** + * Return the server identity. + * + * @return server identity + */ + identification_t* (*get_server_id)(tls_socket_t *this); + + /** + * Return the peer identity. + * + * @return peer identity + */ + identification_t* (*get_peer_id)(tls_socket_t *this); + + /** * Destroy a tls_socket_t. */ void (*destroy)(tls_socket_t *this); diff --git a/src/libtnccs/Makefile.am b/src/libtnccs/Makefile.am index 449d32d92..c6492d8d3 100644 --- a/src/libtnccs/Makefile.am +++ b/src/libtnccs/Makefile.am @@ -1,5 +1,8 @@ -INCLUDES = -I$(top_srcdir)/src/libstrongswan -I$(top_srcdir)/src/libtncif +INCLUDES = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libtncif \ + -I$(top_srcdir)/src/libtls ipseclib_LTLIBRARIES = libtnccs.la diff --git a/src/libtnccs/tnc/tnccs/tnccs.h b/src/libtnccs/tnc/tnccs/tnccs.h index c3020d7c3..fd3e5cabb 100644 --- a/src/libtnccs/tnc/tnccs/tnccs.h +++ b/src/libtnccs/tnc/tnccs/tnccs.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2011 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ typedef struct tnccs_t tnccs_t; typedef enum tnccs_type_t tnccs_type_t; +typedef enum tnc_ift_type_t tnc_ift_type_t; #include <tncif.h> #include <tncifimc.h> @@ -34,6 +35,8 @@ typedef enum tnccs_type_t tnccs_type_t; #include <library.h> #include <plugins/plugin.h> +#include <tls.h> + /** * Type of TNC Client/Server protocol */ @@ -46,17 +49,75 @@ enum tnccs_type_t { }; /** + * Type of TNC Transport protocol + */ +enum tnc_ift_type_t { + TNC_IFT_UNKNOWN, + TNC_IFT_EAP_1_0, + TNC_IFT_EAP_1_1, + TNC_IFT_EAP_2_0, + TNC_IFT_TLS_1_0, + TNC_IFT_TLS_2_0 +}; + +/** * enum names for tnccs_type_t. */ extern enum_name_t *tnccs_type_names; /** + * TNCCS public interface + */ +struct tnccs_t { + + /** + * Implements tls_t + */ + tls_t tls; + + /** + * Get underlying TNC IF-T transport protocol + * + * @return TNC IF-T transport protocol + */ + tnc_ift_type_t (*get_transport)(tnccs_t *this); + + /** + * Set underlying TNC IF-T transport protocol + * + * @param transport TNC IF-T transport protocol + */ + void (*set_transport)(tnccs_t *this, tnc_ift_type_t transport); + + /** + * Get type of TNC Client authentication + * + * @return TNC Client authentication type + */ + u_int32_t (*get_auth_type)(tnccs_t *this); + + /** + * Set type of TNC Client authentication + * + * @param auth_type TNC Client authentication type + */ + void (*set_auth_type)(tnccs_t *this, u_int32_t auth_type); + +}; + +/** * Constructor definition for a pluggable TNCCS protocol implementation. * * @param is_server TRUE if TNC Server, FALSE if TNC Client + * @param server Server identity + * @param peer Client identity + * @param transport Underlying TNC IF-T transport protocol used * @return implementation of the tnccs_t interface */ -typedef tnccs_t *(*tnccs_constructor_t)(bool is_server); +typedef tnccs_t *(*tnccs_constructor_t)(bool is_server, + identification_t *server, + identification_t *peer, + tnc_ift_type_t transport); /** * Callback function adding a message to a TNCCS batch diff --git a/src/libtnccs/tnc/tnccs/tnccs_manager.h b/src/libtnccs/tnc/tnccs/tnccs_manager.h index cbf2dc0e9..4ab9d7e18 100644 --- a/src/libtnccs/tnc/tnccs/tnccs_manager.h +++ b/src/libtnccs/tnc/tnccs/tnccs_manager.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Andreas Steffen + * Copyright (C) 2010-2013 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -56,10 +56,15 @@ struct tnccs_manager_t { * * @param type type of the TNCCS protocol * @param is_server TRUE if TNC Server, FALSE if TNC Client + * @param server Server identity + * @param peer Client identity + * @param transport Underlying TNC IF-T transport protocol used * @return TNCCS protocol instance, NULL if no constructor found */ tnccs_t* (*create_instance)(tnccs_manager_t *this, tnccs_type_t type, - bool is_server); + bool is_server, identification_t *server, + identification_t *peer, + tnc_ift_type_t transport); /** * Create a TNCCS connection and assign a unique connection ID as well a diff --git a/src/libtncif/Android.mk b/src/libtncif/Android.mk index ef406dd59..a337a0dcc 100644 --- a/src/libtncif/Android.mk +++ b/src/libtncif/Android.mk @@ -4,6 +4,7 @@ include $(CLEAR_VARS) # copy-n-paste from Makefile.am LOCAL_SRC_FILES := \ tncif.h tncifimc.h tncifimv.h tncif_names.h tncif_names.c \ +tncif_identity.h tncif_identity.c \ tncif_pa_subtypes.h tncif_pa_subtypes.c # build libtncif --------------------------------------------------------------- diff --git a/src/libtncif/Makefile.am b/src/libtncif/Makefile.am index cc262ffca..6da1201f3 100644 --- a/src/libtncif/Makefile.am +++ b/src/libtncif/Makefile.am @@ -4,6 +4,7 @@ noinst_LTLIBRARIES = libtncif.la libtncif_la_SOURCES = \ tncif.h tncifimc.h tncifimv.h tncif_names.h tncif_names.c \ +tncif_identity.h tncif_identity.c \ tncif_pa_subtypes.h tncif_pa_subtypes.c EXTRA_DIST = Android.mk diff --git a/src/libtncif/tncif_identity.c b/src/libtncif/tncif_identity.c new file mode 100644 index 000000000..66de83dbd --- /dev/null +++ b/src/libtncif/tncif_identity.c @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2013 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 "tncif_identity.h" + +#include <bio/bio_writer.h> +#include <bio/bio_reader.h> +#include <pen/pen.h> +#include <utils/debug.h> + +typedef struct private_tncif_identity_t private_tncif_identity_t; + +/** + * TNC Identity List Attribute Format (TCG TNC IF-IMV 1.4 Draft) + * + * 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 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Identity Count | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RESERVED | Identity Type Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Identity Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Identity Value Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * ~ Identity Value ~ + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RESERVED | Subject Type Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Subject Type | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | RESERVED | Authentication Method Vendor ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Authentication Method | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +/** + * Private data of a tncif_identity_t object. + * + */ +struct private_tncif_identity_t { + + /** + * Public tncif_identity_t interface. + */ + tncif_identity_t public; + + /** + * Identity Type + */ + pen_type_t identity_type; + + /** + * Identity Value + */ + chunk_t identity_value; + + /** + * Subject Type + */ + pen_type_t subject_type; + + /** + * Authentication Type + */ + pen_type_t auth_type; +}; + +METHOD(tncif_identity_t, get_identity_type, pen_type_t, + private_tncif_identity_t *this) +{ + return this->identity_type; +} + +METHOD(tncif_identity_t, get_identity_value, chunk_t, + private_tncif_identity_t *this) +{ + return this->identity_value; +} + +METHOD(tncif_identity_t, get_subject_type, pen_type_t, + private_tncif_identity_t *this) +{ + return this->subject_type; +} + +METHOD(tncif_identity_t, get_auth_type, pen_type_t, + private_tncif_identity_t *this) +{ + return this->auth_type; +} + +METHOD(tncif_identity_t, build, void, + private_tncif_identity_t *this, bio_writer_t *writer) +{ + writer->write_uint32(writer, this->identity_type.vendor_id); + writer->write_uint32(writer, this->identity_type.type); + writer->write_data32(writer, this->identity_value); + writer->write_uint32(writer, this->subject_type.vendor_id); + writer->write_uint32(writer, this->subject_type.type); + writer->write_uint32(writer, this->auth_type.vendor_id); + writer->write_uint32(writer, this->auth_type.type); +} + +METHOD(tncif_identity_t, process, bool, + private_tncif_identity_t *this, bio_reader_t *reader) +{ + u_int8_t reserved; + u_int32_t vendor_id, type; + chunk_t identity_value; + + if (reader->remaining(reader) < TNCIF_IDENTITY_MIN_SIZE) + { + return FALSE; + } + reader->read_uint8 (reader, &reserved); + reader->read_uint24(reader, &vendor_id); + reader->read_uint32(reader, &type); + this->identity_type = pen_type_create(vendor_id, type); + + if (!reader->read_data32(reader, &identity_value) || + reader->remaining(reader) < 16) + { + return FALSE; + } + this->identity_value = chunk_clone(identity_value); + + reader->read_uint8 (reader, &reserved); + reader->read_uint24(reader, &vendor_id); + reader->read_uint32(reader, &type); + this->subject_type = pen_type_create(vendor_id, type); + + reader->read_uint8 (reader, &reserved); + reader->read_uint24(reader, &vendor_id); + reader->read_uint32(reader, &type); + this->auth_type = pen_type_create(vendor_id, type); + + return TRUE; +} + +METHOD(tncif_identity_t, destroy, void, + private_tncif_identity_t *this) +{ + free(this->identity_value.ptr); + free(this); +} + + +/** + * See header + */ +tncif_identity_t *tncif_identity_create_empty(void) +{ + private_tncif_identity_t *this; + + INIT(this, + .public = { + .get_identity_type = _get_identity_type, + .get_identity_value = _get_identity_value, + .get_subject_type = _get_subject_type, + .get_auth_type = _get_auth_type, + .build = _build, + .process = _process, + .destroy = _destroy, + }, + ); + + return &this->public; +} + +/** + * See header + */ +tncif_identity_t *tncif_identity_create(pen_type_t identity_type, + chunk_t identity_value, + pen_type_t subject_type, + pen_type_t auth_type) +{ + private_tncif_identity_t *this; + + this = (private_tncif_identity_t*)tncif_identity_create_empty(); + this->identity_type = identity_type; + this->identity_value = chunk_clone(identity_value); + this->subject_type = subject_type; + this->auth_type = auth_type; + + return &this->public; +} + diff --git a/src/libtncif/tncif_identity.h b/src/libtncif/tncif_identity.h new file mode 100644 index 000000000..3ef0dd4f0 --- /dev/null +++ b/src/libtncif/tncif_identity.h @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2013 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 libtncif libtncif + * + * @addtogroup libtncif + * TNC interface definitions + * + * @defgroup tnc_identities tnc_identities + * @{ @ingroup libtncif + */ + +#ifndef TNCIF_IDENTITY_H_ +#define TNCIF_IDENTITY_H_ + +#include <library.h> + +#include <pen/pen.h> +#include <bio/bio_reader.h> +#include <bio/bio_writer.h> + +#define TNCIF_IDENTITY_MIN_SIZE 28 + +typedef struct tncif_identity_t tncif_identity_t; + +/** + * Public interface of a TNC Identity object + */ +struct tncif_identity_t { + + /** + * Get the TNC Identity Type + * + * @return TNC Identity Type + */ + pen_type_t (*get_identity_type)(tncif_identity_t *this); + + /** + * Get the TNC Identity Value + * + * @return TNC Identity Value + */ + chunk_t (*get_identity_value)(tncif_identity_t *this); + + /** + * Get the TNC Subject Type + * + * @return TNC Subject Type + */ + pen_type_t (*get_subject_type)(tncif_identity_t *this); + + /** + * Get the TNC Authentication Type + * + * @return TNC Authentication Type + */ + pen_type_t (*get_auth_type)(tncif_identity_t *this); + + /** + * Build the IF-IMV TNC Identity attribute encoding + * + * @param writer writer to write encoded data to + */ + void (*build)(tncif_identity_t *this, bio_writer_t *writer); + + /** + * Process the IF-IMV TNC Identity attribute encoding + * + * @param reader reader to read encoded data from + * @return TRUE if successful + */ + bool (*process)(tncif_identity_t *this, bio_reader_t *reader); + + /** + * Destroys a tncif_identity_t object. + */ + void (*destroy)(tncif_identity_t *this); + +}; + +/** + * Create an empty TNC Identity object + */ +tncif_identity_t* tncif_identity_create_empty(void); + +/** + * Create an TNC Identity object from its components + * + * @param identity_type TNC Identity Type + * @param identity_value TNC Identity Value + * @param subject_type TNC Subject Type + * @param auth_type TNC Authentication Type + */ +tncif_identity_t* tncif_identity_create(pen_type_t identity_type, + chunk_t identity_value, + pen_type_t subject_type, + pen_type_t auth_type); + +#endif /** TNCIF_IDENTITY_H_ @}*/ diff --git a/src/libtncif/tncif_names.c b/src/libtncif/tncif_names.c index c108776ec..ac948c8ba 100644 --- a/src/libtncif/tncif_names.c +++ b/src/libtncif/tncif_names.c @@ -45,3 +45,20 @@ ENUM(TNC_IMV_Evaluation_Result_names, "error", "don't know" ); + +ENUM(TNC_Subject_names, + TNC_SUBJECT_UNKNOWN, + TNC_SUBJECT_USER, + "unknown", + "machine", + "user" +); + +ENUM(TNC_Authentication_names, + TNC_AUTH_UNKNOWN, + TNC_AUTH_SIM, + "unknown method", + "certificate", + "password", + "SIM card" +); diff --git a/src/libtncif/tncif_names.h b/src/libtncif/tncif_names.h index 9b50a34e9..75458f960 100644 --- a/src/libtncif/tncif_names.h +++ b/src/libtncif/tncif_names.h @@ -30,5 +30,7 @@ extern enum_name_t *TNC_Connection_State_names; extern enum_name_t *TNC_IMV_Action_Recommendation_names; extern enum_name_t *TNC_IMV_Evaluation_Result_names; +extern enum_name_t *TNC_Subject_names; +extern enum_name_t *TNC_Authentication_names; #endif /** TNCIF_NAME_H_ @}*/ diff --git a/src/libtncif/tncif_pa_subtypes.c b/src/libtncif/tncif_pa_subtypes.c index 135be3c31..bf1e999b3 100644 --- a/src/libtncif/tncif_pa_subtypes.c +++ b/src/libtncif/tncif_pa_subtypes.c @@ -33,11 +33,13 @@ ENUM_NEXT(pa_subtype_ietf_names, PA_SUBTYPE_IETF_ANY, PA_SUBTYPE_IETF_ANY, ); ENUM_END(pa_subtype_ietf_names, PA_SUBTYPE_IETF_ANY); -ENUM_BEGIN(pa_subtype_tcg_names, PA_SUBTYPE_TCG_PTS, PA_SUBTYPE_TCG_PTS, - "PTS" +ENUM_BEGIN(pa_subtype_tcg_names, PA_SUBTYPE_TCG_PTS, PA_SUBTYPE_TCG_SWID, + "PTS", + "SCAP", + "SWID" ); ENUM_NEXT(pa_subtype_tcg_names, PA_SUBTYPE_TCG_ANY, PA_SUBTYPE_TCG_ANY, - PA_SUBTYPE_TCG_PTS, + PA_SUBTYPE_TCG_SWID, "ANY" ); ENUM_END(pa_subtype_tcg_names, PA_SUBTYPE_TCG_ANY); @@ -61,11 +63,12 @@ ENUM_NEXT(pa_subtype_fhh_names, PA_SUBTYPE_FHH_ANY, PA_SUBTYPE_FHH_ANY, ); ENUM_END(pa_subtype_fhh_names, PA_SUBTYPE_FHH_ANY); -ENUM_BEGIN(pa_subtype_ita_names, PA_SUBTYPE_ITA_TEST, PA_SUBTYPE_ITA_TEST, - "Test" +ENUM_BEGIN(pa_subtype_ita_names, PA_SUBTYPE_ITA_TEST, PA_SUBTYPE_ITA_ECHO, + "Test", + "Echo" ); ENUM_NEXT(pa_subtype_ita_names, PA_SUBTYPE_ITA_ANY, PA_SUBTYPE_ITA_ANY, - PA_SUBTYPE_ITA_TEST, + PA_SUBTYPE_ITA_ECHO, "ANY" ); ENUM_END(pa_subtype_ita_names, PA_SUBTYPE_ITA_ANY); diff --git a/src/libtncif/tncif_pa_subtypes.h b/src/libtncif/tncif_pa_subtypes.h index 2dc4c9220..0855d1df3 100644 --- a/src/libtncif/tncif_pa_subtypes.h +++ b/src/libtncif/tncif_pa_subtypes.h @@ -54,6 +54,8 @@ extern enum_name_t *pa_subtype_ietf_names; */ enum pa_subtype_tcg_t { PA_SUBTYPE_TCG_PTS = 0x01, + PA_SUBTYPE_TCG_SCAP = 0x02, + PA_SUBTYPE_TCG_SWID = 0x03, PA_SUBTYPE_TCG_ANY = 0xff }; @@ -84,6 +86,7 @@ extern enum_name_t *pa_subtype_fhh_names; */ enum pa_subtype_ita_t { PA_SUBTYPE_ITA_TEST = 0x01, + PA_SUBTYPE_ITA_ECHO = 0x02, PA_SUBTYPE_ITA_ANY = 0xff }; diff --git a/src/libtncif/tncifimv.h b/src/libtncif/tncifimv.h index 3c9db0055..6bce8b4e4 100644 --- a/src/libtncif/tncifimv.h +++ b/src/libtncif/tncifimv.h @@ -209,6 +209,31 @@ typedef TNC_Result (*TNC_IMV_ProvideBindFunctionPointer)( #define TNC_ATTRIBUTEID_SOH ((TNC_AttributeID) 0x00559706) #define TNC_ATTRIBUTEID_SSOH ((TNC_AttributeID) 0x00559707) #define TNC_ATTRIBUTEID_PRIMARY_IMV_ID ((TNC_AttributeID) 0x00559710) +#define TNC_ATTRIBUTEID_AR_IDENTITIES ((TNC_AttributeID) 0x00559712) + +/* TNC Identity Types */ + +#define TNC_ID_UNKNOWN 0 +#define TNC_ID_IPV4_ADDR 1 +#define TNC_ID_IPV6_ADDR 2 +#define TNC_ID_FQDN 3 +#define TNC_ID_RFC822_ADDR 4 +#define TNC_ID_USER_NAME 5 +#define TNC_ID_DER_ASN1_DN 6 +#define TNC_ID_DER_ASN1_GN 7 + +/* TNC Subject Types */ + +#define TNC_SUBJECT_UNKNOWN 0 +#define TNC_SUBJECT_MACHINE 1 +#define TNC_SUBJECT_USER 2 + +/* TNC Authentication Types */ + +#define TNC_AUTH_UNKNOWN 0 +#define TNC_AUTH_CERT 1 +#define TNC_AUTH_PASSWORD 2 +#define TNC_AUTH_SIM 3 /* IMV Functions */ diff --git a/src/manager/controller/auth_controller.h b/src/manager/controller/auth_controller.h index 41e669fd0..8489d9dd3 100644 --- a/src/manager/controller/auth_controller.h +++ b/src/manager/controller/auth_controller.h @@ -15,7 +15,7 @@ /** * @defgroup auth_controller auth_controller - * @{ @ingroup controller + * @{ @ingroup manager_controller */ #ifndef AUTH_CONTROLLER_H_ diff --git a/src/manager/controller/config_controller.h b/src/manager/controller/config_controller.h index 07cafd4ff..a84678c9a 100644 --- a/src/manager/controller/config_controller.h +++ b/src/manager/controller/config_controller.h @@ -15,7 +15,7 @@ /** * @defgroup config_controller config_controller - * @{ @ingroup controller + * @{ @ingroup manager_controller */ #ifndef CONFIG_CONTROLLER_H_ diff --git a/src/manager/controller/control_controller.h b/src/manager/controller/control_controller.h index c9bc1e4b3..22e3a7022 100644 --- a/src/manager/controller/control_controller.h +++ b/src/manager/controller/control_controller.h @@ -15,7 +15,7 @@ /** * @defgroup control_controller control_controller - * @{ @ingroup controller + * @{ @ingroup manager_controller */ #ifndef CONTROL_CONTROLLER_H_ diff --git a/src/manager/controller/gateway_controller.h b/src/manager/controller/gateway_controller.h index 7d77bdccb..a0999295e 100644 --- a/src/manager/controller/gateway_controller.h +++ b/src/manager/controller/gateway_controller.h @@ -15,7 +15,7 @@ /** * @defgroup gateway_controller gateway_controller - * @{ @ingroup controller + * @{ @ingroup manager_controller */ #ifndef GATEWAY_CONTROLLER_H_ diff --git a/src/manager/controller/ikesa_controller.h b/src/manager/controller/ikesa_controller.h index 3f6779629..72f8242f1 100644 --- a/src/manager/controller/ikesa_controller.h +++ b/src/manager/controller/ikesa_controller.h @@ -15,7 +15,7 @@ /** * @defgroup ikesa_controller ikesa_controller - * @{ @ingroup controller + * @{ @ingroup manager_controller */ #ifndef IKESA_CONTROLLER_H_ diff --git a/src/manager/manager.h b/src/manager/manager.h index f7620833a..a72801f1b 100644 --- a/src/manager/manager.h +++ b/src/manager/manager.h @@ -16,7 +16,7 @@ /** * @defgroup manager manager * - * @defgroup controller controller + * @defgroup manager_controller controller * @ingroup manager * * @defgroup manager_i manager diff --git a/src/medsrv/controller/peer_controller.h b/src/medsrv/controller/peer_controller.h index f25c30281..b5a5e0bb8 100644 --- a/src/medsrv/controller/peer_controller.h +++ b/src/medsrv/controller/peer_controller.h @@ -16,7 +16,7 @@ /** * @defgroup peer_controller_server peer_controller - * @{ @ingroup controller_server + * @{ @ingroup medsrv */ #ifndef PEER_CONTROLLER_H_ @@ -45,4 +45,4 @@ struct peer_controller_t { */ controller_t *peer_controller_create(user_t *user, database_t *db); -#endif /* PEER_CONTROLLER_H_ @} */ +#endif /** PEER_CONTROLLER_H_ @}*/ diff --git a/src/medsrv/controller/user_controller.h b/src/medsrv/controller/user_controller.h index 9d23795d7..540dc74a2 100644 --- a/src/medsrv/controller/user_controller.h +++ b/src/medsrv/controller/user_controller.h @@ -16,7 +16,7 @@ /** * @defgroup user_controller_server user_controller - * @{ @ingroup controller_server + * @{ @ingroup medsrv */ #ifndef USER_CONTROLLER_H_ @@ -45,4 +45,4 @@ struct user_controller_t { */ controller_t *user_controller_create(user_t *user, database_t *db); -#endif /* USER_CONTROLLER_H_ @} */ +#endif /** USER_CONTROLLER_H_ @}*/ diff --git a/src/medsrv/filter/auth_filter.h b/src/medsrv/filter/auth_filter.h index c46de40a5..beae27965 100644 --- a/src/medsrv/filter/auth_filter.h +++ b/src/medsrv/filter/auth_filter.h @@ -16,7 +16,7 @@ /** * @defgroup auth_filter_server auth_filter - * @{ @ingroup filter_server + * @{ @ingroup medsrv */ #ifndef AUTH_FILTER_H_ @@ -45,4 +45,4 @@ struct auth_filter_t { */ filter_t *auth_filter_create(user_t *user, database_t *db); -#endif /* AUTH_FILTER_H_ @}*/ +#endif /** AUTH_FILTER_H_ @}*/ diff --git a/src/medsrv/user.h b/src/medsrv/user.h index f14650f03..beeed6ec1 100644 --- a/src/medsrv/user.h +++ b/src/medsrv/user.h @@ -13,6 +13,13 @@ * for more details. */ +/** + * @defgroup medsrv medsrv + * + * @defgroup user user + * @{ @ingroup medsrv + */ + #ifndef USER_H_ #define USER_H_ @@ -47,4 +54,4 @@ struct user_t { */ user_t *user_create(void *param); -#endif /* USER_H_ @} */ +#endif /** USER_H_ @} */ diff --git a/src/pki/command.h b/src/pki/command.h index a6f8bc758..1a884fb73 100644 --- a/src/pki/command.h +++ b/src/pki/command.h @@ -92,4 +92,4 @@ int command_dispatch(int argc, char *argv[]); */ int command_usage(char *error); -#endif /* COMMAND_H_ @}*/ +#endif /** COMMAND_H_ @}*/ diff --git a/src/pki/commands/pub.c b/src/pki/commands/pub.c index 30078a8fa..9912061f4 100644 --- a/src/pki/commands/pub.c +++ b/src/pki/commands/pub.c @@ -158,7 +158,7 @@ static void __attribute__ ((constructor))reg() pub, 'p', "pub", "extract the public key from a private key/certificate", {"[--in file|--keyid hex] [--type rsa|ecdsa|pkcs10|x509]", - "[--outform der|pem|pgp]"}, + "[--outform der|pem|pgp|dnskey]"}, { {"help", 'h', 0, "show usage information"}, {"in", 'i', 1, "input file, default: stdin"}, diff --git a/src/pki/pki.c b/src/pki/pki.c index 3f77c5e8d..429517b92 100644 --- a/src/pki/pki.c +++ b/src/pki/pki.c @@ -76,6 +76,17 @@ bool get_form(char *form, cred_encoding_type_t *enc, credential_type_t type) return FALSE; } } + else if (streq(form, "dnskey")) + { + switch (type) + { + case CRED_PUBLIC_KEY: + *enc =PUBKEY_DNSKEY; + return TRUE; + default: + return FALSE; + } + } return FALSE; } diff --git a/src/pki/pki.h b/src/pki/pki.h index f72b1804c..09c50c6c2 100644 --- a/src/pki/pki.h +++ b/src/pki/pki.h @@ -15,7 +15,9 @@ /** * @defgroup pki pki - * @{ @ingroup pki + * + * @addtogroup pki + * @{ */ #ifndef PKI_H_ diff --git a/src/scepclient/scep.c b/src/scepclient/scep.c index f2090274c..3fdcd6c28 100644 --- a/src/scepclient/scep.c +++ b/src/scepclient/scep.c @@ -151,8 +151,7 @@ void scep_generate_transaction_id(public_key_t *key, chunk_t *transID, chunk_t digest = chunk_alloca(HASH_SIZE_MD5); chunk_t keyEncoding = chunk_empty, keyInfo; hasher_t *hasher; - bool msb_set; - u_char *pos; + int zeros = 0, msb_set = 0; key->get_encoding(key, PUBKEY_ASN1_DER, &keyEncoding); @@ -168,20 +167,27 @@ void scep_generate_transaction_id(public_key_t *key, chunk_t *transID, DESTROY_IF(hasher); free(keyInfo.ptr); - /* is the most significant bit of the digest set? */ - msb_set = (*digest.ptr & 0x80) == 0x80; - - /* allocate space for the serialNumber */ - serialNumber->len = msb_set + digest.len; - serialNumber->ptr = malloc(serialNumber->len); - - /* the serial number as the two's complement of the digest */ - pos = serialNumber->ptr; + /* the serialNumber should be valid ASN1 integer content: + * remove leading zeros, add one if MSB is set (two's complement) */ + while (zeros < digest.len) + { + if (digest.ptr[zeros]) + { + if (digest.ptr[zeros] & 0x80) + { + msb_set = 1; + } + break; + } + zeros++; + } + *serialNumber = chunk_alloc(digest.len - zeros + msb_set); if (msb_set) { - *pos++ = 0x00; + serialNumber->ptr[0] = 0x00; } - memcpy(pos, digest.ptr, digest.len); + memcpy(serialNumber->ptr + msb_set, digest.ptr + zeros, + digest.len - zeros); /* the transaction id is the serial number in hex format */ *transID = chunk_to_hex(digest, NULL, TRUE); @@ -333,7 +339,7 @@ static char* escape_http_request(chunk_t req) * Send a SCEP request via HTTP and wait for a response */ bool scep_http_request(const char *url, chunk_t msg, scep_op_t op, - bool http_get_request, chunk_t *response) + bool http_get_request, u_int timeout, chunk_t *response) { int len; status_t status; @@ -361,6 +367,7 @@ bool scep_http_request(const char *url, chunk_t msg, scep_op_t op, status = lib->fetcher->fetch(lib->fetcher, complete_url, response, FETCH_HTTP_VERSION_1_0, + FETCH_TIMEOUT, timeout, FETCH_REQUEST_HEADER, "Pragma:", FETCH_REQUEST_HEADER, "Host:", FETCH_REQUEST_HEADER, "Accept:", @@ -375,6 +382,7 @@ bool scep_http_request(const char *url, chunk_t msg, scep_op_t op, status = lib->fetcher->fetch(lib->fetcher, complete_url, response, FETCH_HTTP_VERSION_1_0, + FETCH_TIMEOUT, timeout, FETCH_REQUEST_DATA, msg, FETCH_REQUEST_TYPE, "", FETCH_REQUEST_HEADER, "Expect:", @@ -403,6 +411,7 @@ bool scep_http_request(const char *url, chunk_t msg, scep_op_t op, status = lib->fetcher->fetch(lib->fetcher, complete_url, response, FETCH_HTTP_VERSION_1_0, + FETCH_TIMEOUT, timeout, FETCH_END); } diff --git a/src/scepclient/scep.h b/src/scepclient/scep.h index 30551d2db..ec8fa6515 100644 --- a/src/scepclient/scep.h +++ b/src/scepclient/scep.h @@ -79,7 +79,7 @@ chunk_t scep_build_request(chunk_t data, chunk_t transID, scep_msg_t msg, size_t key_size, certificate_t *signer_cert, hash_algorithm_t digest_alg, private_key_t *private_key); bool scep_http_request(const char *url, chunk_t message, scep_op_t op, - bool http_get_request, chunk_t *response); + bool http_get_request, u_int timeout, chunk_t *response); err_t scep_parse_response(chunk_t response, chunk_t transID, container_t **out, scep_attributes_t *attrs); diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c index 83b5d6219..26f210d12 100644 --- a/src/scepclient/scepclient.c +++ b/src/scepclient/scepclient.c @@ -113,6 +113,9 @@ long crl_check_interval = 0; /* by default pluto logs out after every smartcard use */ bool pkcs11_keep_state = FALSE; +/* by default HTTP fetch timeout is 30s */ +static u_int http_timeout = 30; + /* options read by optionsfrom */ options_t *options; @@ -344,6 +347,7 @@ static void usage(const char *message) " - if no filename is given, default is used\n" " --optionsfrom (-+) <filename> reads additional options from given file\n" " --force (-f) force existing file(s)\n" + " --httptimeout (-T) timeout for HTTP operations (default: 30s)\n" "\n" "Options for key generation (pkcs1):\n" " --keylength (-k) <bits> key length for RSA key generation\n" @@ -518,6 +522,7 @@ int main(int argc, char **argv) { "in", required_argument, NULL, 'i' }, { "out", required_argument, NULL, 'o' }, { "force", no_argument, NULL, 'f' }, + { "httptimeout", required_argument, NULL, 'T' }, { "keylength", required_argument, NULL, 'k' }, { "dn", required_argument, NULL, 'd' }, { "days", required_argument, NULL, 'D' }, @@ -662,6 +667,14 @@ int main(int argc, char **argv) force = TRUE; continue; + case 'T': /* --httptimeout */ + http_timeout = atoi(optarg); + if (http_timeout <= 0) + { + usage("invalid httptimeout specified"); + } + continue; + case '+': /* --optionsfrom <filename> */ if (!options->from(options, optarg, &argc, &argv, optind)) { @@ -939,7 +952,8 @@ int main(int argc, char **argv) pkcs7_t *pkcs7; if (!scep_http_request(scep_url, chunk_create(ca_name, strlen(ca_name)), - SCEP_GET_CA_CERT, http_get_request, &scep_response)) + SCEP_GET_CA_CERT, http_get_request, + http_timeout, &scep_response)) { exit_scepclient("did not receive a valid scep response"); } @@ -1317,7 +1331,7 @@ int main(int argc, char **argv) creds->add_cert(creds, TRUE, x509_ca_sig->get_ref(x509_ca_sig)); if (!scep_http_request(scep_url, pkcs7, SCEP_PKI_OPERATION, - http_get_request, &scep_response)) + http_get_request, http_timeout, &scep_response)) { exit_scepclient("did not receive a valid scep response"); } @@ -1337,7 +1351,7 @@ int main(int argc, char **argv) poll_start = time_monotonic(NULL); issuerAndSubject = asn1_wrap(ASN1_SEQUENCE, "cc", issuer->get_encoding(issuer), - subject); + subject->get_encoding(subject)); } while (attrs.pkiStatus == SCEP_PENDING) { @@ -1367,7 +1381,7 @@ int main(int argc, char **argv) exit_scepclient("failed to build scep request"); } if (!scep_http_request(scep_url, getCertInitial, SCEP_PKI_OPERATION, - http_get_request, &scep_response)) + http_get_request, http_timeout, &scep_response)) { exit_scepclient("did not receive a valid scep response"); } @@ -1458,5 +1472,3 @@ int main(int argc, char **argv) exit_scepclient(NULL); return -1; /* should never be reached */ } - - diff --git a/src/starter/args.c b/src/starter/args.c index 390062a99..5fbf51856 100644 --- a/src/starter/args.c +++ b/src/starter/args.c @@ -33,6 +33,7 @@ typedef enum { ARG_TIME, ARG_ULNG, ARG_ULLI, + ARG_UBIN, ARG_PCNT, ARG_STR, ARG_LST, @@ -146,6 +147,7 @@ static const token_info_t token_info[] = { ARG_MISC, 0, NULL /* KW_MOBIKE */ }, { ARG_MISC, 0, NULL /* KW_FORCEENCAPS */ }, { ARG_ENUM, offsetof(starter_conn_t, fragmentation), LST_fragmentation }, + { ARG_UBIN, offsetof(starter_conn_t, ikedscp), NULL }, { ARG_TIME, offsetof(starter_conn_t, sa_ike_life_seconds), NULL }, { ARG_TIME, offsetof(starter_conn_t, sa_ipsec_life_seconds), NULL }, { ARG_TIME, offsetof(starter_conn_t, sa_rekey_margin), NULL }, @@ -399,6 +401,21 @@ bool assign_arg(kw_token_t token, kw_token_t first, kw_list_t *kw, char *base, } } break; + case ARG_UBIN: + { + char *endptr; + u_int *u = (u_int *)p; + + *u = strtoul(kw->value, &endptr, 2); + + if (*endptr != '\0') + { + DBG1(DBG_APP, "# bad binary value: %s=%s", kw->entry->name, + kw->value); + return FALSE; + } + } + break; case ARG_TIME: { char *endptr; diff --git a/src/starter/cmp.c b/src/starter/cmp.c index aaba7b11d..cea864a4a 100644 --- a/src/starter/cmp.c +++ b/src/starter/cmp.c @@ -27,7 +27,8 @@ static bool starter_cmp_end(starter_end_t *c1, starter_end_t *c2) return FALSE; VARCMP(modecfg); - VARCMP(port); + VARCMP(from_port); + VARCMP(to_port); VARCMP(protocol); return cmp_args(KW_END_FIRST, KW_END_LAST, (char *)c1, (char *)c2); @@ -63,4 +64,3 @@ bool starter_cmp_ca(starter_ca_t *c1, starter_ca_t *c2) return cmp_args(KW_CA_NAME, KW_CA_LAST, (char *)c1, (char *)c2); } - diff --git a/src/starter/confread.c b/src/starter/confread.c index fecb998df..883534aad 100644 --- a/src/starter/confread.c +++ b/src/starter/confread.c @@ -142,6 +142,9 @@ static void default_values(starter_config_t *cfg) cfg->conn_default.left.ikeport = 500; cfg->conn_default.right.ikeport = 500; + cfg->conn_default.left.to_port = 0xffff; + cfg->conn_default.right.to_port = 0xffff; + cfg->ca_default.seen = SEEN_NONE; } @@ -292,24 +295,46 @@ static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token, } if (streq(port, "%any")) { - end->port = 0; + end->from_port = 0; + end->to_port = 0xffff; } - else + else if (streq(port, "%opaque")) + { + end->from_port = 0xffff; + end->to_port = 0; + } + else if (*port) { svc = getservbyname(port, NULL); if (svc) { - end->port = ntohs(svc->s_port); + end->from_port = end->to_port = ntohs(svc->s_port); } else { p = strtol(port, &endptr, 0); - if ((*port && *endptr) || p < 0 || p > 0xffff) + if (p < 0 || p > 0xffff) + { + DBG1(DBG_APP, "# bad port: %s=%s", name, port); + goto err; + } + end->from_port = p; + if (*endptr == '-') + { + port = endptr + 1; + p = strtol(port, &endptr, 0); + if (p < 0 || p > 0xffff) + { + DBG1(DBG_APP, "# bad port: %s=%s", name, port); + goto err; + } + } + end->to_port = p; + if (*endptr) { - DBG1(DBG_APP, "# bad port: %s=%s", name, value); + DBG1(DBG_APP, "# bad port: %s=%s", name, port); goto err; } - end->port = (u_int16_t)p; } } if (sep) diff --git a/src/starter/confread.h b/src/starter/confread.h index a0f6234f9..0690bed4e 100644 --- a/src/starter/confread.h +++ b/src/starter/confread.h @@ -115,7 +115,8 @@ struct starter_end { bool hostaccess; bool allow_any; char *updown; - u_int16_t port; + u_int16_t from_port; + u_int16_t to_port; u_int8_t protocol; char *sourceip; char *dns; @@ -148,6 +149,7 @@ struct starter_conn { ipsec_mode_t mode; bool proxy_mode; fragmentation_t fragmentation; + u_int ikedscp; sa_option_t options; time_t sa_ike_life_seconds; time_t sa_ipsec_life_seconds; @@ -246,4 +248,3 @@ extern starter_config_t *confread_load(const char *file); extern void confread_free(starter_config_t *cfg); #endif /* _IPSEC_CONFREAD_H_ */ - diff --git a/src/starter/keywords.h b/src/starter/keywords.h index f776f33c9..4a96a418c 100644 --- a/src/starter/keywords.h +++ b/src/starter/keywords.h @@ -43,6 +43,7 @@ typedef enum { KW_MOBIKE, KW_FORCEENCAPS, KW_FRAGMENTATION, + KW_IKEDSCP, KW_IKELIFETIME, KW_KEYLIFE, KW_REKEYMARGIN, @@ -186,4 +187,3 @@ typedef enum { } kw_token_t; #endif /* _KEYWORDS_H_ */ - diff --git a/src/starter/keywords.txt b/src/starter/keywords.txt index 1f1641287..cd964b0e3 100644 --- a/src/starter/keywords.txt +++ b/src/starter/keywords.txt @@ -41,6 +41,7 @@ aaa_identity, KW_AAA_IDENTITY mobike, KW_MOBIKE forceencaps, KW_FORCEENCAPS fragmentation, KW_FRAGMENTATION +ikedscp, KW_IKEDSCP, ikelifetime, KW_IKELIFETIME lifetime, KW_KEYLIFE keylife, KW_KEYLIFE diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c index 4f9e8fb14..cc447c41f 100644 --- a/src/starter/starterstroke.c +++ b/src/starter/starterstroke.c @@ -146,7 +146,8 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta msg_end->tohost = !conn_end->subnet; msg_end->allow_any = conn_end->allow_any; msg_end->protocol = conn_end->protocol; - msg_end->port = conn_end->port; + msg_end->from_port = conn_end->from_port; + msg_end->to_port = conn_end->to_port; } int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn) @@ -181,6 +182,7 @@ int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn) msg.add_conn.mobike = conn->options & SA_OPTION_MOBIKE; msg.add_conn.force_encap = conn->options & SA_OPTION_FORCE_ENCAP; msg.add_conn.fragmentation = conn->fragmentation; + msg.add_conn.ikedscp = conn->ikedscp; msg.add_conn.ipcomp = conn->options & SA_OPTION_COMPRESS; msg.add_conn.install_policy = conn->install_policy; msg.add_conn.aggressive = conn->aggressive; @@ -330,4 +332,3 @@ int starter_stroke_configure(starter_config_t *cfg) } return 0; } - diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c index e289296c1..c2a505141 100644 --- a/src/stroke/stroke.c +++ b/src/stroke/stroke.c @@ -151,12 +151,14 @@ static int add_connection(char *name, msg.add_conn.me.ikeport = 500; msg.add_conn.me.subnets = push_string(&msg, my_nets); msg.add_conn.me.sendcert = 1; + msg.add_conn.me.to_port = 65535; msg.add_conn.other.id = push_string(&msg, other_id); msg.add_conn.other.address = push_string(&msg, other_addr); msg.add_conn.other.ikeport = 500; msg.add_conn.other.subnets = push_string(&msg, other_nets); msg.add_conn.other.sendcert = 1; + msg.add_conn.other.to_port = 65535; return send_stroke_msg(&msg); } diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h index e972a5984..a9c6f2369 100644 --- a/src/stroke/stroke_msg.h +++ b/src/stroke/stroke_msg.h @@ -167,7 +167,8 @@ struct stroke_end_t { int tohost; int allow_any; u_int8_t protocol; - u_int16_t port; + u_int16_t from_port; + u_int16_t to_port; }; typedef struct stroke_msg_t stroke_msg_t; @@ -262,6 +263,7 @@ struct stroke_msg_t { int close_action; u_int32_t reqid; u_int32_t tfc; + u_int8_t ikedscp; crl_policy_t crl_policy; int unique; diff --git a/testing/config/kernel/config-3.8 b/testing/config/kernel/config-3.8 new file mode 100644 index 000000000..bbd423ecf --- /dev/null +++ b/testing/config/kernel/config-3.8 @@ -0,0 +1,1863 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/x86_64 3.8.1 Kernel Configuration +# +CONFIG_64BIT=y +CONFIG_X86_64=y +CONFIG_X86=y +CONFIG_INSTRUCTION_DECODER=y +CONFIG_OUTPUT_FORMAT="elf64-x86-64" +CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_HAVE_LATENCYTOP_SUPPORT=y +CONFIG_MMU=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_NEED_SG_DMA_LENGTH=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_GENERIC_BUG=y +CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_ARCH_MAY_HAVE_PC_FDC=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_ARCH_HAS_CPU_RELAX=y +CONFIG_ARCH_HAS_DEFAULT_IDLE=y +CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y +CONFIG_ARCH_HAS_CPU_AUTOPROBE=y +CONFIG_HAVE_SETUP_PER_CPU_AREA=y +CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y +CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y +CONFIG_ARCH_HIBERNATION_POSSIBLE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ZONE_DMA32=y +CONFIG_AUDIT_ARCH=y +CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y +CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y +CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11" +CONFIG_ARCH_SUPPORTS_UPROBES=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y +CONFIG_IRQ_WORK=y +CONFIG_BUILDTIME_EXTABLE_SORT=y + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_BZIP2=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_POSIX_MQUEUE=y +CONFIG_POSIX_MQUEUE_SYSCTL=y +# CONFIG_FHANDLE is not set +# CONFIG_AUDIT is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_FORCED_THREADING=y +CONFIG_SPARSE_IRQ=y +CONFIG_CLOCKSOURCE_WATCHDOG=y +CONFIG_ARCH_CLOCKSOURCE_DATA=y +CONFIG_GENERIC_TIME_VSYSCALL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y +CONFIG_GENERIC_CMOS_UPDATE=y + +# +# Timers subsystem +# +CONFIG_TICK_ONESHOT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y + +# +# CPU/Task time and stats accounting +# +CONFIG_TICK_CPU_ACCOUNTING=y +# CONFIG_IRQ_TIME_ACCOUNTING is not set +CONFIG_BSD_PROCESS_ACCT=y +# CONFIG_BSD_PROCESS_ACCT_V3 is not set +# CONFIG_TASKSTATS is not set + +# +# RCU Subsystem +# +CONFIG_TINY_RCU=y +# CONFIG_PREEMPT_RCU is not set +# CONFIG_TREE_RCU_TRACE is not set +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y +CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y +CONFIG_ARCH_WANTS_PROT_NUMA_PROT_NONE=y +# CONFIG_CGROUPS is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +# CONFIG_BLK_DEV_INITRD is not set +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +# CONFIG_EXPERT is not set +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_SYSCTL_EXCEPTION_TRACE=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_PCSPKR_PLATFORM=y +CONFIG_HAVE_PCSPKR_PLATFORM=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y +# CONFIG_EMBEDDED is not set +CONFIG_HAVE_PERF_EVENTS=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +CONFIG_COMPAT_BRK=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_PROFILING is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_OPROFILE_NMI_TIMER=y +# CONFIG_JUMP_LABEL is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y +CONFIG_HAVE_IOREMAP_PROT=y +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_OPTPROBES=y +CONFIG_HAVE_ARCH_TRACEHOOK=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BREAKPOINT=y +CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y +CONFIG_HAVE_USER_RETURN_NOTIFIER=y +CONFIG_HAVE_PERF_EVENTS_NMI=y +CONFIG_HAVE_PERF_REGS=y +CONFIG_HAVE_PERF_USER_STACK_DUMP=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y +CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y +CONFIG_HAVE_CMPXCHG_LOCAL=y +CONFIG_HAVE_CMPXCHG_DOUBLE=y +CONFIG_HAVE_ARCH_SECCOMP_FILTER=y +CONFIG_SECCOMP_FILTER=y +CONFIG_HAVE_CONTEXT_TRACKING=y +CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y +CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y +CONFIG_MODULES_USE_ELF_RELA=y +CONFIG_GENERIC_SIGALTSTACK=y + +# +# GCOV-based kernel profiling +# +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_SLABINFO=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +# CONFIG_MODULES is not set +CONFIG_BLOCK=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +CONFIG_EFI_PARTITION=y + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_INLINE_SPIN_UNLOCK_IRQ=y +CONFIG_INLINE_READ_UNLOCK=y +CONFIG_INLINE_READ_UNLOCK_IRQ=y +CONFIG_INLINE_WRITE_UNLOCK=y +CONFIG_INLINE_WRITE_UNLOCK_IRQ=y +CONFIG_FREEZER=y + +# +# Processor type and features +# +CONFIG_ZONE_DMA=y +# CONFIG_SMP is not set +CONFIG_X86_MPPARSE=y +CONFIG_X86_EXTENDED_PLATFORM=y +CONFIG_SCHED_OMIT_FRAME_POINTER=y +CONFIG_PARAVIRT_GUEST=y +# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set +# CONFIG_XEN is not set +# CONFIG_XEN_PRIVILEGED_GUEST is not set +CONFIG_KVM_GUEST=y +CONFIG_PARAVIRT=y +CONFIG_PARAVIRT_CLOCK=y +# CONFIG_PARAVIRT_DEBUG is not set +CONFIG_NO_BOOTMEM=y +# CONFIG_MEMTEST is not set +# CONFIG_MK8 is not set +# CONFIG_MPSC is not set +CONFIG_MCORE2=y +# CONFIG_MATOM is not set +# CONFIG_GENERIC_CPU is not set +CONFIG_X86_INTERNODE_CACHE_SHIFT=6 +CONFIG_X86_L1_CACHE_SHIFT=6 +CONFIG_X86_INTEL_USERCOPY=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_X86_P6_NOP=y +CONFIG_X86_TSC=y +CONFIG_X86_CMPXCHG64=y +CONFIG_X86_CMOV=y +CONFIG_X86_MINIMUM_CPU_FAMILY=64 +CONFIG_X86_DEBUGCTLMSR=y +CONFIG_CPU_SUP_INTEL=y +CONFIG_CPU_SUP_AMD=y +CONFIG_CPU_SUP_CENTAUR=y +CONFIG_HPET_TIMER=y +CONFIG_DMI=y +CONFIG_GART_IOMMU=y +# CONFIG_CALGARY_IOMMU is not set +CONFIG_SWIOTLB=y +CONFIG_IOMMU_HELPER=y +CONFIG_NR_CPUS=1 +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_X86_LOCAL_APIC=y +CONFIG_X86_IO_APIC=y +# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set +# CONFIG_X86_MCE is not set +# CONFIG_I8K is not set +# CONFIG_MICROCODE is not set +# CONFIG_X86_MSR is not set +# CONFIG_X86_CPUID is not set +CONFIG_ARCH_PHYS_ADDR_T_64BIT=y +CONFIG_ARCH_DMA_ADDR_T_64BIT=y +CONFIG_DIRECT_GBPAGES=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_ARCH_MEMORY_PROBE=y +CONFIG_ARCH_PROC_KCORE_TEXT=y +CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y +CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y +CONFIG_SPARSEMEM_VMEMMAP=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_HAVE_MEMBLOCK_NODE_MAP=y +CONFIG_ARCH_DISCARD_MEMBLOCK=y +CONFIG_MEMORY_ISOLATION=y +CONFIG_MEMORY_HOTPLUG=y +CONFIG_MEMORY_HOTPLUG_SPARSE=y +CONFIG_MEMORY_HOTREMOVE=y +CONFIG_PAGEFLAGS_EXTENDED=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +CONFIG_MIGRATION=y +CONFIG_PHYS_ADDR_T_64BIT=y +CONFIG_ZONE_DMA_FLAG=1 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +# CONFIG_TRANSPARENT_HUGEPAGE is not set +CONFIG_CROSS_MEMORY_ATTACH=y +CONFIG_NEED_PER_CPU_KM=y +# CONFIG_CLEANCACHE is not set +# CONFIG_FRONTSWAP is not set +# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set +CONFIG_X86_RESERVE_LOW=64 +CONFIG_MTRR=y +CONFIG_MTRR_SANITIZER=y +CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0 +CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1 +CONFIG_X86_PAT=y +CONFIG_ARCH_USES_PG_UNCACHED=y +CONFIG_ARCH_RANDOM=y +CONFIG_X86_SMAP=y +# CONFIG_EFI is not set +CONFIG_SECCOMP=y +# CONFIG_CC_STACKPROTECTOR is not set +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +CONFIG_SCHED_HRTICK=y +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +CONFIG_PHYSICAL_START=0x1000000 +CONFIG_RELOCATABLE=y +CONFIG_PHYSICAL_ALIGN=0x1000000 +# CONFIG_CMDLINE_BOOL is not set +CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y +CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y + +# +# Power management and ACPI options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +# CONFIG_HIBERNATION is not set +CONFIG_PM_SLEEP=y +# CONFIG_PM_AUTOSLEEP is not set +# CONFIG_PM_WAKELOCKS is not set +# CONFIG_PM_RUNTIME is not set +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +CONFIG_ACPI=y +CONFIG_ACPI_SLEEP=y +# CONFIG_ACPI_PROCFS is not set +# CONFIG_ACPI_PROCFS_POWER is not set +# CONFIG_ACPI_EC_DEBUGFS is not set +CONFIG_ACPI_PROC_EVENT=y +CONFIG_ACPI_AC=y +CONFIG_ACPI_BATTERY=y +CONFIG_ACPI_BUTTON=y +CONFIG_ACPI_FAN=y +# CONFIG_ACPI_DOCK is not set +CONFIG_ACPI_PROCESSOR=y +# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set +CONFIG_ACPI_THERMAL=y +# CONFIG_ACPI_CUSTOM_DSDT is not set +# CONFIG_ACPI_INITRD_TABLE_OVERRIDE is not set +CONFIG_ACPI_BLACKLIST_YEAR=0 +# CONFIG_ACPI_DEBUG is not set +# CONFIG_ACPI_PCI_SLOT is not set +CONFIG_X86_PM_TIMER=y +# CONFIG_ACPI_CONTAINER is not set +# CONFIG_ACPI_HOTPLUG_MEMORY is not set +# CONFIG_ACPI_SBS is not set +# CONFIG_ACPI_HED is not set +# CONFIG_ACPI_APEI is not set +# CONFIG_SFI is not set + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set +CONFIG_CPU_IDLE=y +# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set +# CONFIG_INTEL_IDLE is not set + +# +# Memory power savings +# +# CONFIG_I7300_IDLE is not set + +# +# Bus options (PCI etc.) +# +CONFIG_PCI=y +CONFIG_PCI_DIRECT=y +# CONFIG_PCI_MMCONFIG is not set +CONFIG_PCI_DOMAINS=y +# CONFIG_PCIEPORTBUS is not set +CONFIG_ARCH_SUPPORTS_MSI=y +CONFIG_PCI_MSI=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +# CONFIG_PCI_STUB is not set +CONFIG_HT_IRQ=y +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +# CONFIG_PCI_IOAPIC is not set +CONFIG_PCI_LABEL=y +CONFIG_ISA_DMA_API=y +CONFIG_AMD_NB=y +# CONFIG_PCCARD is not set +# CONFIG_HOTPLUG_PCI is not set +# CONFIG_RAPIDIO is not set + +# +# Executable file formats / Emulations +# +CONFIG_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_HAVE_AOUT is not set +# CONFIG_BINFMT_MISC is not set +CONFIG_COREDUMP=y +# CONFIG_IA32_EMULATION is not set +CONFIG_HAVE_TEXT_POKE_SMP=y +CONFIG_X86_DEV_DMA_OPS=y +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_DIAG is not set +CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +CONFIG_XFRM_ALGO=y +CONFIG_XFRM_USER=y +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_MIGRATE=y +CONFIG_XFRM_STATISTICS=y +CONFIG_XFRM_IPCOMP=y +CONFIG_NET_KEY=y +CONFIG_NET_KEY_MIGRATE=y +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_MULTIPATH is not set +# CONFIG_IP_ROUTE_VERBOSE is not set +CONFIG_IP_ROUTE_CLASSID=y +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_NET_IPVTI is not set +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_INET_XFRM_TUNNEL=y +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y +# CONFIG_IPV6_PRIVACY is not set +# CONFIG_IPV6_ROUTER_PREF is not set +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_TUNNEL=y +CONFIG_INET6_TUNNEL=y +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_SIT is not set +CONFIG_IPV6_TUNNEL=y +CONFIG_IPV6_GRE=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=y +# CONFIG_NETFILTER_NETLINK_ACCT is not set +CONFIG_NETFILTER_NETLINK_QUEUE=y +CONFIG_NETFILTER_NETLINK_LOG=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_MARK=y +# CONFIG_NF_CONNTRACK_ZONES is not set +CONFIG_NF_CONNTRACK_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +# CONFIG_NF_CT_PROTO_DCCP is not set +# CONFIG_NF_CT_PROTO_SCTP is not set +CONFIG_NF_CT_PROTO_UDPLITE=y +# CONFIG_NF_CONNTRACK_AMANDA is not set +# CONFIG_NF_CONNTRACK_FTP is not set +# CONFIG_NF_CONNTRACK_H323 is not set +# CONFIG_NF_CONNTRACK_IRC is not set +# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set +# CONFIG_NF_CONNTRACK_SNMP is not set +# CONFIG_NF_CONNTRACK_PPTP is not set +CONFIG_NF_CONNTRACK_SANE=y +# CONFIG_NF_CONNTRACK_SIP is not set +# CONFIG_NF_CONNTRACK_TFTP is not set +CONFIG_NF_CT_NETLINK=y +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set +# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set +CONFIG_NF_NAT=y +CONFIG_NF_NAT_NEEDED=y +CONFIG_NF_NAT_PROTO_UDPLITE=y +# CONFIG_NF_NAT_AMANDA is not set +# CONFIG_NF_NAT_FTP is not set +# CONFIG_NF_NAT_IRC is not set +# CONFIG_NF_NAT_SIP is not set +# CONFIG_NF_NAT_TFTP is not set +# CONFIG_NETFILTER_TPROXY is not set +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=y +CONFIG_NETFILTER_XT_CONNMARK=y +CONFIG_NETFILTER_XT_SET=y + +# +# Xtables targets +# +# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_CT=y +CONFIG_NETFILTER_XT_TARGET_DSCP=y +CONFIG_NETFILTER_XT_TARGET_HL=y +# CONFIG_NETFILTER_XT_TARGET_HMARK is not set +# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NETMAP=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_NOTRACK=y +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +CONFIG_NETFILTER_XT_TARGET_REDIRECT=y +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y +CONFIG_NETFILTER_XT_MATCH_CLUSTER=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +CONFIG_NETFILTER_XT_MATCH_DCCP=y +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=y +CONFIG_NETFILTER_XT_MATCH_DSCP=y +CONFIG_NETFILTER_XT_MATCH_ECN=y +CONFIG_NETFILTER_XT_MATCH_ESP=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_HL=y +# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set +CONFIG_NETFILTER_XT_MATCH_LENGTH=y +CONFIG_NETFILTER_XT_MATCH_LIMIT=y +CONFIG_NETFILTER_XT_MATCH_MAC=y +CONFIG_NETFILTER_XT_MATCH_MARK=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +CONFIG_NETFILTER_XT_MATCH_REALM=y +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +CONFIG_NETFILTER_XT_MATCH_SCTP=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +CONFIG_NETFILTER_XT_MATCH_TCPMSS=y +# CONFIG_NETFILTER_XT_MATCH_TIME is not set +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_IP_SET=y +CONFIG_IP_SET_MAX=256 +CONFIG_IP_SET_BITMAP_IP=y +CONFIG_IP_SET_BITMAP_IPMAC=y +CONFIG_IP_SET_BITMAP_PORT=y +CONFIG_IP_SET_HASH_IP=y +CONFIG_IP_SET_HASH_IPPORT=y +CONFIG_IP_SET_HASH_IPPORTIP=y +CONFIG_IP_SET_HASH_IPPORTNET=y +CONFIG_IP_SET_HASH_NET=y +CONFIG_IP_SET_HASH_NETPORT=y +# CONFIG_IP_SET_HASH_NETIFACE is not set +CONFIG_IP_SET_LIST_SET=y +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +CONFIG_IP_NF_QUEUE=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +# CONFIG_IP_NF_MATCH_RPFILTER is not set +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_TARGET_ULOG=y +CONFIG_NF_NAT_IPV4=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +# CONFIG_NF_NAT_PPTP is not set +# CONFIG_NF_NAT_H323 is not set +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_TARGET_CLUSTERIP=y +CONFIG_IP_NF_TARGET_ECN=y +CONFIG_IP_NF_TARGET_TTL=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARP_MANGLE=y + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_AH=y +CONFIG_IP6_NF_MATCH_EUI64=y +CONFIG_IP6_NF_MATCH_FRAG=y +CONFIG_IP6_NF_MATCH_OPTS=y +CONFIG_IP6_NF_MATCH_HL=y +CONFIG_IP6_NF_MATCH_IPV6HEADER=y +CONFIG_IP6_NF_MATCH_MH=y +# CONFIG_IP6_NF_MATCH_RPFILTER is not set +CONFIG_IP6_NF_MATCH_RT=y +CONFIG_IP6_NF_TARGET_HL=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_NF_NAT_IPV6=y +CONFIG_IP6_NF_TARGET_MASQUERADE=y +CONFIG_IP6_NF_TARGET_NPT=y +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_L2TP=y +# CONFIG_L2TP_V3 is not set +# CONFIG_BRIDGE is not set +CONFIG_HAVE_NET_DSA=y +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set +# CONFIG_NET_SCHED is not set +# CONFIG_DCB is not set +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_BQL=y + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +# CONFIG_CFG80211 is not set +# CONFIG_LIB80211 is not set + +# +# CFG80211 needs to be enabled for MAC80211 +# +# CONFIG_WIMAX is not set +# CONFIG_RFKILL is not set +CONFIG_NET_9P=y +CONFIG_NET_9P_VIRTIO=y +# CONFIG_NET_9P_DEBUG is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set +CONFIG_HAVE_BPF_JIT=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +# CONFIG_DMA_SHARED_BUFFER is not set + +# +# Bus devices +# +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_PNP=y +CONFIG_PNP_DEBUG_MESSAGES=y + +# +# Protocols +# +CONFIG_PNPACPI=y +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_DRBD is not set +CONFIG_BLK_DEV_NBD=y +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_VIRTIO_BLK=y +# CONFIG_BLK_DEV_HD is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_IBM_ASM is not set +# CONFIG_PHANTOM is not set +# CONFIG_INTEL_MID_PTI is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_VMWARE_BALLOON is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_CB710_CORE is not set + +# +# Texas Instruments shared transport line discipline +# + +# +# Altera FPGA firmware download module +# +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set +# CONFIG_SCSI is not set +# CONFIG_SCSI_DMA is not set +# CONFIG_SCSI_NETLINK is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# CONFIG_I2O is not set +# CONFIG_MACINTOSH_DRIVERS is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +CONFIG_DUMMY=y +# CONFIG_EQUALIZER is not set +# CONFIG_MII is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_VXLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +CONFIG_TUN=y +# CONFIG_VETH is not set +CONFIG_VIRTIO_NET=y +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# + +# +# Distributed Switch Architecture drivers +# +# CONFIG_NET_DSA_MV88E6XXX is not set +# CONFIG_NET_DSA_MV88E6060 is not set +# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set +# CONFIG_NET_DSA_MV88E6131 is not set +# CONFIG_NET_DSA_MV88E6123_61_65 is not set +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_ALTEON=y +# CONFIG_ACENIC is not set +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +CONFIG_NET_CADENCE=y +# CONFIG_ARM_AT91_ETHER is not set +# CONFIG_MACB is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2X is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +# CONFIG_NET_TULIP is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_EXAR=y +# CONFIG_S2IO is not set +# CONFIG_VXGE is not set +CONFIG_NET_VENDOR_HP=y +# CONFIG_HP100 is not set +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +CONFIG_NET_VENDOR_I825XX=y +# CONFIG_ZNET is not set +# CONFIG_IP1000 is not set +# CONFIG_JME is not set +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_MVMDIO is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX4_CORE is not set +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8851_MLL is not set +# CONFIG_KSZ884X_PCI is not set +CONFIG_NET_VENDOR_MYRI=y +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NATSEMI=y +# CONFIG_NATSEMI is not set +# CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_8390=y +# CONFIG_NE2K_PCI is not set +CONFIG_NET_VENDOR_NVIDIA=y +# CONFIG_FORCEDETH is not set +CONFIG_NET_VENDOR_OKI=y +# CONFIG_PCH_GBE is not set +# CONFIG_ETHOC is not set +CONFIG_NET_PACKET_ENGINE=y +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_NETXEN_NIC is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_SEEQ=y +# CONFIG_SEEQ8005 is not set +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +# CONFIG_SFC is not set +CONFIG_NET_VENDOR_SMSC=y +# CONFIG_EPIC100 is not set +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_TEHUTI=y +# CONFIG_TEHUTI is not set +CONFIG_NET_VENDOR_TI=y +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +CONFIG_NET_VENDOR_WIZNET=y +# CONFIG_WIZNET_W5100 is not set +# CONFIG_WIZNET_W5300 is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +# CONFIG_NET_SB1000 is not set +# CONFIG_PHYLIB is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set +CONFIG_WLAN=y +# CONFIG_AIRO is not set +# CONFIG_ATMEL is not set +# CONFIG_PRISM54 is not set +# CONFIG_HOSTAP is not set +# CONFIG_WL_TI is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set +# CONFIG_INPUT_MATRIXKMAP is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_LKKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_LIFEBOOK=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_SERIO_ARC_PS2 is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +# CONFIG_TRACE_SINK is not set +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set +CONFIG_FIX_EARLYCON_MEM=y + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MFD_HSU is not set +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_SCCNXP is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_PCH_UART is not set +# CONFIG_SERIAL_ARC is not set +CONFIG_HVC_DRIVER=y +CONFIG_VIRTIO_CONSOLE=y +# CONFIG_IPMI_HANDLER is not set +# CONFIG_HW_RANDOM is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_MWAVE is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_HPET is not set +# CONFIG_HANGCHECK_TIMER is not set +# CONFIG_TCG_TPM is not set +# CONFIG_TELCLOCK is not set +CONFIG_DEVPORT=y +# CONFIG_I2C is not set +# CONFIG_SPI is not set +# CONFIG_HSI is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# +# CONFIG_PTP_1588_CLOCK is not set + +# +# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. +# +# CONFIG_PTP_1588_CLOCK_PCH is not set +CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y +# CONFIG_GPIOLIB is not set +# CONFIG_W1 is not set +CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_POWER_RESET is not set +# CONFIG_POWER_AVS is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_ABITUGURU is not set +# CONFIG_SENSORS_ABITUGURU3 is not set +# CONFIG_SENSORS_K8TEMP is not set +# CONFIG_SENSORS_K10TEMP is not set +# CONFIG_SENSORS_FAM15H_POWER is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_CORETEMP is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_MAX197 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_VIA_CPUTEMP is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_SENSORS_APPLESMC is not set + +# +# ACPI drivers +# +# CONFIG_SENSORS_ACPI_POWER is not set +# CONFIG_SENSORS_ATK0110 is not set +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y +# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set +# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set +# CONFIG_FAIR_SHARE is not set +CONFIG_STEP_WISE=y +# CONFIG_USER_SPACE is not set +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_RTSX_PCI is not set +# CONFIG_MFD_TI_AM335X_TSCADC is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_MFD_CS5535 is not set +# CONFIG_LPC_SCH is not set +# CONFIG_LPC_ICH is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_REGULATOR is not set +# CONFIG_MEDIA_SUPPORT is not set + +# +# Graphics support +# +# CONFIG_AGP is not set +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +# CONFIG_VGA_SWITCHEROO is not set +# CONFIG_DRM is not set +# CONFIG_STUB_POULSBO is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set +# CONFIG_EXYNOS_VIDEO is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set +# CONFIG_SND is not set +# CONFIG_SOUND_PRIME is not set + +# +# HID support +# +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set +# CONFIG_UHID is not set +CONFIG_HID_GENERIC=y + +# +# Special HID drivers +# +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB_ARCH_HAS_XHCI=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# +# CONFIG_USB_GADGET is not set + +# +# OTG and related infrastructure +# +# CONFIG_UWB is not set +# CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +# CONFIG_EDAC is not set +# CONFIG_RTC_CLASS is not set +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set +CONFIG_VIRTIO=y + +# +# Virtio drivers +# +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_MMIO=y +# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set + +# +# Microsoft Hyper-V guest support +# +# CONFIG_HYPERV is not set +# CONFIG_STAGING is not set +CONFIG_X86_PLATFORM_DEVICES=y +# CONFIG_ACERHDF is not set +# CONFIG_ASUS_LAPTOP is not set +# CONFIG_FUJITSU_TABLET is not set +# CONFIG_HP_ACCEL is not set +# CONFIG_THINKPAD_ACPI is not set +# CONFIG_SENSORS_HDAPS is not set +# CONFIG_INTEL_MENLOW is not set +# CONFIG_ACPI_WMI is not set +# CONFIG_TOPSTAR_LAPTOP is not set +# CONFIG_TOSHIBA_BT_RFKILL is not set +# CONFIG_ACPI_CMPC is not set +# CONFIG_INTEL_IPS is not set +# CONFIG_IBM_RTL is not set +# CONFIG_XO15_EBOOK is not set +# CONFIG_SAMSUNG_Q10 is not set + +# +# Hardware Spinlock drivers +# +CONFIG_CLKEVT_I8253=y +CONFIG_I8253_LOCK=y +CONFIG_CLKBLD_I8253=y +CONFIG_IOMMU_SUPPORT=y +# CONFIG_AMD_IOMMU is not set +# CONFIG_INTEL_IOMMU is not set +# CONFIG_IRQ_REMAP is not set + +# +# Remoteproc drivers (EXPERIMENTAL) +# +# CONFIG_STE_MODEM_RPROC is not set + +# +# Rpmsg drivers (EXPERIMENTAL) +# +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_EXTCON is not set +# CONFIG_MEMORY is not set +# CONFIG_IIO is not set +# CONFIG_VME_BUS is not set +# CONFIG_PWM is not set +# CONFIG_IPACK_BUS is not set + +# +# Firmware Drivers +# +# CONFIG_EDD is not set +CONFIG_FIRMWARE_MEMMAP=y +# CONFIG_DELL_RBU is not set +# CONFIG_DCDBAS is not set +CONFIG_DMIID=y +# CONFIG_DMI_SYSFS is not set +# CONFIG_ISCSI_IBFT_FIND is not set +# CONFIG_GOOGLE_FIRMWARE is not set + +# +# File systems +# +CONFIG_DCACHE_WORD_ACCESS=y +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +# CONFIG_EXT3_FS_XATTR is not set +# CONFIG_EXT4_FS is not set +CONFIG_JBD=y +CONFIG_REISERFS_FS=y +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_REISERFS_FS_XATTR is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +CONFIG_QUOTA=y +# CONFIG_QUOTA_NETLINK_INTERFACE is not set +CONFIG_PRINT_QUOTA_WARNING=y +# CONFIG_QUOTA_DEBUG is not set +# CONFIG_QFMT_V1 is not set +# CONFIG_QFMT_V2 is not set +CONFIG_QUOTACTL=y +CONFIG_AUTOFS4_FS=y +# CONFIG_FUSE_FS is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +CONFIG_JOLIET=y +# CONFIG_ZISOFS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_MSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +# CONFIG_F2FS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +# CONFIG_NFS_FS is not set +# CONFIG_NFSD is not set +# CONFIG_CEPH_FS is not set +# CONFIG_CIFS is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_9P_FS=y +CONFIG_9P_FS_POSIX_ACL=y +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ASCII is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_MAC_ROMAN is not set +# CONFIG_NLS_MAC_CELTIC is not set +# CONFIG_NLS_MAC_CENTEURO is not set +# CONFIG_NLS_MAC_CROATIAN is not set +# CONFIG_NLS_MAC_CYRILLIC is not set +# CONFIG_NLS_MAC_GAELIC is not set +# CONFIG_NLS_MAC_GREEK is not set +# CONFIG_NLS_MAC_ICELAND is not set +# CONFIG_NLS_MAC_INUIT is not set +# CONFIG_NLS_MAC_ROMANIAN is not set +# CONFIG_NLS_MAC_TURKISH is not set +# CONFIG_NLS_UTF8 is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=1024 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_READABLE_ASM is not set +# CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_PANIC_ON_OOPS is not set +CONFIG_PANIC_ON_OOPS_VALUE=0 +CONFIG_DETECT_HUNG_TASK=y +CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 +# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set +CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 +# CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_HAVE_DEBUG_KMEMLEAK=y +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_VIRTUAL is not set +# CONFIG_DEBUG_WRITECOUNT is not set +CONFIG_DEBUG_MEMORY_INIT=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +CONFIG_ARCH_WANT_FRAME_POINTERS=y +CONFIG_FRAME_POINTER=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_NOTIFIER_ERROR_INJECTION is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_LATENCYTOP is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_USER_STACKTRACE_SUPPORT=y +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y +CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_SYSCALL_TRACEPOINTS=y +CONFIG_HAVE_FENTRY=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +CONFIG_FTRACE=y +# CONFIG_FUNCTION_TRACER is not set +# CONFIG_IRQSOFF_TRACER is not set +# CONFIG_SCHED_TRACER is not set +# CONFIG_ENABLE_DEFAULT_TRACERS is not set +# CONFIG_FTRACE_SYSCALLS is not set +CONFIG_BRANCH_PROFILE_NONE=y +# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set +# CONFIG_PROFILE_ALL_BRANCHES is not set +# CONFIG_STACK_TRACER is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_UPROBE_EVENT is not set +# CONFIG_PROBE_EVENTS is not set +# CONFIG_MMIOTRACE is not set +# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +CONFIG_HAVE_ARCH_KMEMCHECK=y +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_X86_VERBOSE_BOOTUP=y +CONFIG_EARLY_PRINTK=y +# CONFIG_EARLY_PRINTK_DBGP is not set +# CONFIG_DEBUG_STACKOVERFLOW is not set +# CONFIG_X86_PTDUMP is not set +CONFIG_DEBUG_RODATA=y +CONFIG_DEBUG_RODATA_TEST=y +# CONFIG_DEBUG_TLBFLUSH is not set +# CONFIG_IOMMU_DEBUG is not set +# CONFIG_IOMMU_STRESS is not set +CONFIG_HAVE_MMIOTRACE_SUPPORT=y +CONFIG_IO_DELAY_TYPE_0X80=0 +CONFIG_IO_DELAY_TYPE_0XED=1 +CONFIG_IO_DELAY_TYPE_UDELAY=2 +CONFIG_IO_DELAY_TYPE_NONE=3 +CONFIG_IO_DELAY_0X80=y +# CONFIG_IO_DELAY_0XED is not set +# CONFIG_IO_DELAY_UDELAY is not set +# CONFIG_IO_DELAY_NONE is not set +CONFIG_DEFAULT_IO_DELAY_TYPE=0 +# CONFIG_CPA_DEBUG is not set +# CONFIG_OPTIMIZE_INLINING is not set +# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set +# CONFIG_DEBUG_NMI_SELFTEST is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITYFS is not set +CONFIG_DEFAULT_SECURITY_DAC=y +CONFIG_DEFAULT_SECURITY="" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +CONFIG_CRYPTO_USER=y +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +CONFIG_CRYPTO_GF128MUL=y +CONFIG_CRYPTO_NULL=y +CONFIG_CRYPTO_WORKQUEUE=y +CONFIG_CRYPTO_CRYPTD=y +CONFIG_CRYPTO_AUTHENC=y +CONFIG_CRYPTO_ABLK_HELPER_X86=y +CONFIG_CRYPTO_GLUE_HELPER_X86=y + +# +# Authenticated Encryption with Associated Data +# +CONFIG_CRYPTO_CCM=y +CONFIG_CRYPTO_GCM=y +CONFIG_CRYPTO_SEQIV=y + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +CONFIG_CRYPTO_CTR=y +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_LRW=y +CONFIG_CRYPTO_PCBC=y +CONFIG_CRYPTO_XTS=y + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_XCBC=y +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_CRC32C_INTEL is not set +CONFIG_CRYPTO_GHASH=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_MICHAEL_MIC=y +CONFIG_CRYPTO_RMD128=y +CONFIG_CRYPTO_RMD160=y +CONFIG_CRYPTO_RMD256=y +CONFIG_CRYPTO_RMD320=y +CONFIG_CRYPTO_SHA1=y +# CONFIG_CRYPTO_SHA1_SSSE3 is not set +CONFIG_CRYPTO_SHA256=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_TGR192=y +CONFIG_CRYPTO_WP512=y +# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_X86_64=y +CONFIG_CRYPTO_AES_NI_INTEL=y +CONFIG_CRYPTO_ANUBIS=y +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_BLOWFISH=y +CONFIG_CRYPTO_BLOWFISH_COMMON=y +CONFIG_CRYPTO_BLOWFISH_X86_64=y +CONFIG_CRYPTO_CAMELLIA=y +CONFIG_CRYPTO_CAMELLIA_X86_64=y +CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64=y +CONFIG_CRYPTO_CAST_COMMON=y +CONFIG_CRYPTO_CAST5=y +CONFIG_CRYPTO_CAST5_AVX_X86_64=y +CONFIG_CRYPTO_CAST6=y +CONFIG_CRYPTO_CAST6_AVX_X86_64=y +CONFIG_CRYPTO_DES=y +CONFIG_CRYPTO_FCRYPT=y +CONFIG_CRYPTO_KHAZAD=y +CONFIG_CRYPTO_SALSA20=y +CONFIG_CRYPTO_SALSA20_X86_64=y +CONFIG_CRYPTO_SEED=y +CONFIG_CRYPTO_SERPENT=y +CONFIG_CRYPTO_SERPENT_SSE2_X86_64=y +CONFIG_CRYPTO_SERPENT_AVX_X86_64=y +CONFIG_CRYPTO_TEA=y +CONFIG_CRYPTO_TWOFISH=y +CONFIG_CRYPTO_TWOFISH_COMMON=y +CONFIG_CRYPTO_TWOFISH_X86_64=y +CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=y +CONFIG_CRYPTO_TWOFISH_AVX_X86_64=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +CONFIG_CRYPTO_ZLIB=y +CONFIG_CRYPTO_LZO=y + +# +# Random Number Generation +# +# CONFIG_CRYPTO_ANSI_CPRNG is not set +CONFIG_CRYPTO_USER_API=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +# CONFIG_CRYPTO_HW is not set +CONFIG_HAVE_KVM=y +CONFIG_VIRTUALIZATION=y +# CONFIG_KVM is not set +# CONFIG_VHOST_NET is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_STRNCPY_FROM_USER=y +CONFIG_GENERIC_STRNLEN_USER=y +CONFIG_GENERIC_FIND_FIRST_BIT=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_PERCPU_RWSEM=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +CONFIG_CRC_ITU_T=y +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +CONFIG_CRC7=y +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=y +CONFIG_TEXTSEARCH_BM=y +CONFIG_TEXTSEARCH_FSM=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set +# CONFIG_DDR is not set diff --git a/testing/hosts/winnetou/etc/bind/K.+008+32329.key b/testing/hosts/winnetou/etc/bind/K.+008+32329.key new file mode 100644 index 000000000..9f4e5ea5d --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/K.+008+32329.key @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 32329, for . +; Created: 20130213194956 (Wed Feb 13 20:49:56 2013) +; Publish: 20130213194956 (Wed Feb 13 20:49:56 2013) +; Activate: 20130213194956 (Wed Feb 13 20:49:56 2013) +. IN DNSKEY 257 3 8 AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2 XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5 nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO O9fOgGnjzAk= diff --git a/testing/hosts/winnetou/etc/bind/K.+008+32329.private b/testing/hosts/winnetou/etc/bind/K.+008+32329.private new file mode 100644 index 000000000..8ad5cd6ae --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/K.+008+32329.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: tyyRqtq0WC+C9eXRs2rgjjdkHN32Nieg+qwhwDRqGpeVRNRr5zZfM3aZLsMZwjhnkaf7y/8iHiVAlCuV/0j9zYeOigICwrVsDlxFLYOJT5svoZ7Scu2805/gLQwcYutZwM42DlCgvQ5wW8xe5S068OSggx218NgNJzET29KiRz3xLHnnf8xPGmyxd4z2L45q4aqiEhlT4xVF1bC8k+J4IvsxrhsC22Ab4pJtDLvH+pc8hKirPAZC8LGwv3d+8P9ymn4rOKoDSgf4N+vK9zmdZ0J2triBjPtYIUXBxjU9bo9svmJ7iOeOXdZbGim7NPjocpE7EOET4U47186AaePMCQ== +PublicExponent: AQAB +PrivateExponent: cOOQ6uFa4DZ32aBHuvGVb1CH7JqHER0fQx4utswW0Ei3f/IChj6mMYtYIM+w4lfszIHg1vpoRnfi8u5hxTFw6egvWrKejO1OqRMIt2Inj94uXscJIDeQdkRD3r9mBzjQ2di8y9m5For9iDXODiPv/WKJ4gS/iq08ffjrKkEILirduFpG+EcopBy4MJeAMAkATkRsATEHgEbyqulP7gMwAnQ6vXFbTybfZQWWSgANabGikKMmGroJMChBGJ2Q9c7mHVpXu2IhMqYRKHWmBA5v/OrEc21dNxRGXsZuq+iu3P8o5MLHgX6YDB9nB3OVb47Prg/BxHYdQid2PwX0A0qZeQ== +Prime1: 2ovikMXe1sTJ2xYPHgofDMmDXUwgpHu/nsCbdDHhyHIMllLXWsefuAFGQug/DDDg69oZGhNkah53uU9XAEyy6uiFJKgnzBTqCg+QmuZnuiuiQ4QjZ/g2x6R2MvzTZLOAQOaOLA3GVsgOh5msyO1kaatES4m2Pbp3xF6CYkhVRlc= +Prime2: 1pDSXUoE/dwWCebwJHyKLQ3RSGn1o3EHeKZKnqZpABMSPs7imeoVQVZomidjUjHxkB9jbE8nqN15U/Ui4WuZKM+LPbiknaC+h2Y8v6p3u5XQSR0l1cWwdo7BZtdUkcuqSwpL0mnwnmLc6ZQrr13GXnk3qm1ymXST3MFWCWjyRJ8= +Exponent1: 02q1b8XrT6qpd2a8kxvJc85RZWTqwxPviDzdZaeHuygRYy6apHgu24toE/umWj3CqIag9+fAoSP+P+cvy9tmzfbILnD5puSoj7kE88RmnePuIhBnTAIDxFgl/Cc2vNkk/iPLb3SX5YW9AJK6Ytm75LlI5SZAhTCpAe9HhJpi3Bs= +Exponent2: deHfEY3nLCnMmegdK46Yw6QBxU0hvYgN2MVT3dIDghz4OzWi3Xjz8I+urHLTaIcz9kCoeQsL+QSk8fGOFlbtMLTGBUT6e/eidfU/jvXzDkaCxoiTDt2r05cevoezWN6SUuP3QEUgA4TBZjsXvSNCJwlmAeZbvd+ElRZLVKQp5nU= +Coefficient: mtSrbS9kgU1yoTaaY4C6jTnfa43wvHi9pGHW5TUSjRQ9YnCsxy6GiuhmCcKB4iDUzWvIHehfGF5A8UaIF4GvIWcSj1FYO1uBrre5mKMxk89Y7oGtwF2qVbpPHAL4GKHPOUzmfr0vR+nT1PFs1Gr1BF+hkYgluh05KEu0flOZoAk= +Created: 20130213194956 +Publish: 20130213194956 +Activate: 20130213194956 diff --git a/testing/hosts/winnetou/etc/bind/K.+008+43749.key b/testing/hosts/winnetou/etc/bind/K.+008+43749.key new file mode 100644 index 000000000..de00dec2d --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/K.+008+43749.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 43749, for . +; Created: 20130213194939 (Wed Feb 13 20:49:39 2013) +; Publish: 20130213194939 (Wed Feb 13 20:49:39 2013) +; Activate: 20130213194939 (Wed Feb 13 20:49:39 2013) +. IN DNSKEY 256 3 8 AwEAAdMS+CyW9m8yB6rwrqsdfMW41AWim1T/ehg4Un/9qADFEZN9T7NK 9PI+DD3Dr72Z2ZO4hrKXB2Xe0nlvsCUjTfCwdGqgz9YLv2WfXzqRksxF gQXmzAdG7JGH+7YmXq7AAF3246caa+wMXAGRdUUCiQf87CnAaZXJ1kUz wHw3Arp5 diff --git a/testing/hosts/winnetou/etc/bind/K.+008+43749.private b/testing/hosts/winnetou/etc/bind/K.+008+43749.private new file mode 100644 index 000000000..fb0f442f3 --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/K.+008+43749.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: 0xL4LJb2bzIHqvCuqx18xbjUBaKbVP96GDhSf/2oAMURk31Ps0r08j4MPcOvvZnZk7iGspcHZd7SeW+wJSNN8LB0aqDP1gu/ZZ9fOpGSzEWBBebMB0bskYf7tiZersAAXfbjpxpr7AxcAZF1RQKJB/zsKcBplcnWRTPAfDcCunk= +PublicExponent: AQAB +PrivateExponent: MWEqtiPLG1B1AsSz2ExZuFf5IihcdpIeGjRy+IZ7G1L/PaX/U06h51okuv5gytaHVEvDF1zF2ks6qjY62zVbMhr69/a6XjP6QWtiDmJgAnOjRqnKs8ZfEE3rsdauDtPPUIclNr9LnJtOz32oVlvxQXn/zVCE421eKlIKZIS0AEE= +Prime1: 8iaE9VEf9lmYEBM7m5Z/maTvP+RjYvmVx7gdnBDzHkw1ZZkc/27sSI1bvgPZ55ZSiH+324OHwQp3A5m2P9th1Q== +Prime2: 3yVw5TpfBOSteVUMtkvUqI7o0TnUoMeGuKZyXUo8GfQz8oGKoZgmdBJTETmmV4gXPtaEMFUxD4PhJw5ralrkFQ== +Exponent1: QPWeY2Tw6xhb16whKHr2HhSF7iDpnIqR6LL2loBhh/YvuOKbSdbK4iexvcawtRS5bU691tBxIZMaHEgnAPhsRQ== +Exponent2: iw5B9BcT73CxydJ+QXuv4fpsizWGk0rDYX4X9pq0KVhMpuqjAWBXVi21Jh7O0e00zyvO5G+ySwDb5gLOXVCWoQ== +Coefficient: b46+74v/ETHVVKxqdXZWf9r5RL/08AyxScYrT5qDXhJ+QeGZa1jRxrWp469FWltzliP68jLh2om6F4IjAK5o0g== +Created: 20130213194939 +Publish: 20130213194939 +Activate: 20130213194939 diff --git a/testing/hosts/winnetou/etc/bind/Korg.+008+24285.key b/testing/hosts/winnetou/etc/bind/Korg.+008+24285.key new file mode 100644 index 000000000..44043b485 --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/Korg.+008+24285.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 24285, for org. +; Created: 20130213191908 (Wed Feb 13 20:19:08 2013) +; Publish: 20130213191908 (Wed Feb 13 20:19:08 2013) +; Activate: 20130213191908 (Wed Feb 13 20:19:08 2013) +org. IN DNSKEY 256 3 8 AwEAAa6IO30MFlgyj0hJLe0vqvHLr1/4kRCNl/Biz7VYwgzRkiYxHxLJ U+i8/r9rEWU85Q6WEt77xQ+HyxzwmoXpSaMtymYifNFZnvwl31CbkzIB FTtBUQ3BCKZjv0WgpLExDqAKgclCWBZ1PrHvDn1HTl6mMgCpiWothzkn zoNbB0g9 diff --git a/testing/hosts/winnetou/etc/bind/Korg.+008+24285.private b/testing/hosts/winnetou/etc/bind/Korg.+008+24285.private new file mode 100644 index 000000000..e707bb6bb --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/Korg.+008+24285.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: rog7fQwWWDKPSEkt7S+q8cuvX/iREI2X8GLPtVjCDNGSJjEfEslT6Lz+v2sRZTzlDpYS3vvFD4fLHPCahelJoy3KZiJ80Vme/CXfUJuTMgEVO0FRDcEIpmO/RaCksTEOoAqByUJYFnU+se8OfUdOXqYyAKmJai2HOSfOg1sHSD0= +PublicExponent: AQAB +PrivateExponent: Enac/HSL5Jasq7P6JM5XIi8vBVMRXZPtD+QUHxYdqSd+c4XcyKr9snBT7sIP3AreHHXp1ycBSMxPw2b8oc/1Fx5UcCdfL2Sygw2l9oDG2nVWX5taLZgNe1t+Bbsf7fqUxBu0fYHx42xvRHPNwV+8VsDa2TDGRImH8MlPuVbHt2E= +Prime1: 375Bu+m6egBN6k2P82oE8mUuLVYnJDOQ90ipG6Vcfxy7HTzObX+Ismw171oMASLrwMV8UWohp8cbFiira/4ruQ== +Prime2: x7G7d58Pycz+Wox3ez8/livTQ4wXYb/ykUzgycOVJaPPRX9siz10rVfl5Y3sXQlsR4xFSl6GKFAc11MbmS7qpQ== +Exponent1: aPk+pgd28h6Kb8+MJkwrnf5St/qfyqBW924jyVDAIPM95u3MfBtF61BRzcaVs0LLEVqWhSwiNjF4R+E07CoIIQ== +Exponent2: T3kaZJb3D5b3u02f13rqcXdrkrxUKeDcRptT8rhVyS8SNFRr/FYu8zXCFsOOx9ASOb9HbDuGJNENSVyX5TTYyQ== +Coefficient: GsFR4s38eNTqazXvDLcSG+166dSIRRWUrIMR85veIchQY7lsFTRFEmwKX43OsXvSZUMIE2svwIgclhP/FefcUw== +Created: 20130213191908 +Publish: 20130213191908 +Activate: 20130213191908 diff --git a/testing/hosts/winnetou/etc/bind/Korg.+008+51859.key b/testing/hosts/winnetou/etc/bind/Korg.+008+51859.key new file mode 100644 index 000000000..7a617ecbe --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/Korg.+008+51859.key @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 51859, for org. +; Created: 20130213191920 (Wed Feb 13 20:19:20 2013) +; Publish: 20130213191920 (Wed Feb 13 20:19:20 2013) +; Activate: 20130213191920 (Wed Feb 13 20:19:20 2013) +org. IN DNSKEY 257 3 8 AwEAAfAyiINF1/fIyebiAZhG3kFxv1+j3D3TxNBPccbiVUgYSnse95mb mn40KgguCljoi6kDu10Qo+XUwpR78dGJiqvKfej7cz6wbIr5qu9Kv7f8 lJPRQ2igxZ/0ZCLXGbozRuQGy39klQeG98fwxNkzHqXRxkhyAgpY8E2B umRsi2Cca/vKF+6OpNx9b8RXIBcUTdhx0Vjg+3gYhSRR1rPB160sbaL+ v3Fxv9ZzOIY9ekforNxuqV9/U0DCiOhgpZC7H+5ShPb0VNzYvv0IwIAG VPVEJdh5SNPQ0LclPXcR3av+DpjvdY5oAOn/mLPCHjxBnzOl7Q3P43dL DtYdKb9mGnk= diff --git a/testing/hosts/winnetou/etc/bind/Korg.+008+51859.private b/testing/hosts/winnetou/etc/bind/Korg.+008+51859.private new file mode 100644 index 000000000..698cb4f80 --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/Korg.+008+51859.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: 8DKIg0XX98jJ5uIBmEbeQXG/X6PcPdPE0E9xxuJVSBhKex73mZuafjQqCC4KWOiLqQO7XRCj5dTClHvx0YmKq8p96PtzPrBsivmq70q/t/yUk9FDaKDFn/RkItcZujNG5AbLf2SVB4b3x/DE2TMepdHGSHICCljwTYG6ZGyLYJxr+8oX7o6k3H1vxFcgFxRN2HHRWOD7eBiFJFHWs8HXrSxtov6/cXG/1nM4hj16R+is3G6pX39TQMKI6GClkLsf7lKE9vRU3Ni+/QjAgAZU9UQl2HlI09DQtyU9dxHdq/4OmO91jmgA6f+Ys8IePEGfM6XtDc/jd0sO1h0pv2YaeQ== +PublicExponent: AQAB +PrivateExponent: pJ69mNqhbZ0bYzW6Shcn9Ep1EqNHKsictvf7zocIU+TyBvfuUkSm2Z/+vqRvSwf1z9xS6TGiYr4yrXlU/nr5o0ugh7DuByT6/zSlxmLAiuR9H+HoBSlKyJnCl248n7TM/TL6/VB+Iy6JW2rUPtgeRR9EehpI87aI21Xx3SnXTFoUTP7Z9HwoWEPOaU1SfYvBDLjZ0GTtMJ4i/LRB/rC6sbetqru4MTCAhsr8VrcH6YsFu5JrlmG+/dTEi005DrZPUOnKaDf4w3TbgSeTfbFJmvpfOoJObGm+Pc1PtxgfVUVdDWGK/LSNbTdqPQkPGlOI1sUETFNMKOY0S66H5q44QQ== +Prime1: /y8kGw8mAtAuvISUtlUao7srcSphvvMLpxvgOB22u2wgzD51VdPRr2Inv1SJN7SGoJ9ERNLnfBnc1KFBOqtvf5uOwHD4++U80H+qWS+1aNgmMEa+IQ5WamQSPvUWFkhF6TjJnwY4rATfK2FGh00n6O3IOMjDxYyDs/M/j62/VQ0= +Prime2: 8PcgSGgYGveDwkocfVkF0uuWRMVtfY3O/tiYSuCfkFP/++7eKMXQekmBay+5a5YUSZ6UwDFqduC/tYIuvGBi0rv+lzZJ8ydz/sdmQ+aqS3/g6oerGaTUjRV560OKWCwiMIfwQqaN+ivXdBFgGCJnaah65wiQ9W0xeTJqORQxWB0= +Exponent1: dL3+SJrPiu3u07PbzOZ2P317TFRVT2QlapfoJgQB+xBmmMniKBe1kATZpkBoXiGqjYUPWGUcHbw/OM9k5hBT/A8QaZ3FaoffIIunRRH8bjCkl+VlSf4jLp0Fc+Pv7NW3lhCyvJu+BYRdDJ1+BJwZrAhMVx4R4ih8gDDCXVrhc2k= +Exponent2: QQvEuCb5UtY7yAevdxq/2rbjon7U1o6gMOUQ/y1xhUlXkY9igwkbBNewytlgKS2jHlhjeRodzidPONUCfrFaG97Jk9IA1lVxF3aGIZAzqhvEACtNQafgBJGmjp51yuVm+UjIz4UcUErjZx6FnR40Yi4rtw/16XpnX3r/d5b+1vU= +Coefficient: hAE0/Fdc6enFMymrfGW8o4lDauKQj7yQ16hw3IoOlrRLUpXqLiEnk+J6kzkSqgiW+ZC2v5Qq8mTC/3Q//ddWgaLX/LlbItitTlhQCS7hlV33ZkyvLBBjonYztnI+LHnIkj/omjumEzeQGR40TAh4FAgByRNXG2IOrLavfR/iPC8= +Created: 20130213191920 +Publish: 20130213191920 +Activate: 20130213191920 diff --git a/testing/hosts/winnetou/etc/bind/Kstrongswan.org.+008+00481.key b/testing/hosts/winnetou/etc/bind/Kstrongswan.org.+008+00481.key new file mode 100644 index 000000000..a2d755ff4 --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/Kstrongswan.org.+008+00481.key @@ -0,0 +1,5 @@ +; This is a key-signing key, keyid 481, for strongswan.org. +; Created: 20130213175556 (Wed Feb 13 18:55:56 2013) +; Publish: 20130213175556 (Wed Feb 13 18:55:56 2013) +; Activate: 20130213175556 (Wed Feb 13 18:55:56 2013) +strongswan.org. IN DNSKEY 257 3 8 AwEAAcXfcWvCGzQq80q9JX1Wvz0lwA/fi1XZmega350wGR8WdFCklvmK fAzNaf1CrvN3bH9Gl2VEEhkYMF6h6kVFTU7taspq5t0bLwgCK/nS8QzK TLWvzWdyVayiHfij1PPwnQV5FADBTE5mMEkmn82+PKg6jaKs3ANsc0BP bGSsGIxhUKliLxJEd+6KSl/+ouQD9RfCD5sz9NIF+IXv1ZGp2Rjf+6vK bPO8f0hmttwE/OzKyBgysLBbd6fw2pKOBhunVFmUYPaHM9zLTydzuSIA X9iSeM6HtAvlKgK0JGgPEFrX+jPG6wDvJfzzakx85rMkRGc31NFiFLqM ooWxy1674/U= diff --git a/testing/hosts/winnetou/etc/bind/Kstrongswan.org.+008+00481.private b/testing/hosts/winnetou/etc/bind/Kstrongswan.org.+008+00481.private new file mode 100644 index 000000000..cfa7e83c4 --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/Kstrongswan.org.+008+00481.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: xd9xa8IbNCrzSr0lfVa/PSXAD9+LVdmZ6BrfnTAZHxZ0UKSW+Yp8DM1p/UKu83dsf0aXZUQSGRgwXqHqRUVNTu1qymrm3RsvCAIr+dLxDMpMta/NZ3JVrKId+KPU8/CdBXkUAMFMTmYwSSafzb48qDqNoqzcA2xzQE9sZKwYjGFQqWIvEkR37opKX/6i5AP1F8IPmzP00gX4he/VkanZGN/7q8ps87x/SGa23AT87MrIGDKwsFt3p/Dako4GG6dUWZRg9ocz3MtPJ3O5IgBf2JJ4zoe0C+UqArQkaA8QWtf6M8brAO8l/PNqTHzmsyREZzfU0WIUuoyihbHLXrvj9Q== +PublicExponent: AQAB +PrivateExponent: SIEdgEy5xx3N1B8Gs6yrmm5QuABDgAuh94iRU3miWt/RcxM8NuflmJNUOPbMQG4MFX76TqLotsVERAi0XPmN4FPig5U0TuR9EUQqdPo0VWlzPkfSzgr5Fa65qLfvegs6nhzFlZk+qqOLIeLDP5Jri4EZEPiiDacZfAEeSK0+uYDxxNCSShcYFqd9kIcqFS9pk0tcqVOZY55xjEHlk35+N08TvC+H6OnFyppz24TAuU9vqxtdGYEt6+BXnwG8MI6hCv16PkHJKeJVeC3tIl+cO+TYMMaWeI+8MXX+GIfyAOaAGj0pi3BnpUOiiLtwO0P3mi7mxB2/0Jzx2c8lLvLqaQ== +Prime1: 8UFH1F2bt+1B2ssTHiPq+nqw/VYMTVUw+Hju79hVg2TugP0OEat00BqmZU4+bI1YscpwmWHZAU8wHvhMyjomol4+KplqxALXes3WMTijs9qXZIAX48yuakWyOrPLgUdNYwnvtcrC0vxJXk9G1lhOXDzHxmLD+HVd37SlUGvFvy8= +Prime2: 0fdlpeBJzmDDLYz7GP2oCLhuxvUXl4xFKDDJMAikdjgpZI8wTHAyNOY9BQMZGDUkrozrxWzYpcDLyEuhVfQFl7fvlOy6c8cnHPar6JPLFhcV1g2tSiXGnUVfusVytwtDdApAPKVtFeaC3HX+jil0SmO4uqw6wXtkwwsH7aeMZhs= +Exponent1: Utd/usSJ/BZUTrT805Sx02Dd9Z/eiY9/SVL9eQ5oDr5Rx6kdc6PUcME18gN0HAJNOn+xOnoG8hQnCftpIufk7ExAPJCBwNzY8SpNKomwbMnawn/ZtDdMjOFx2gZzEulRAXkf/uSpEZnf96pxQJkCD1ovn0e600459d8qBPt847E= +Exponent2: Y+w99rwPw+Su3j2qvhDxZ/0F0y+O47OAsgjNpktmoVBG+rFeRfJbImuz/G+mAKxB4cP07IbJb9CZ6p97j2FLTBHgNdqXPUQ47ALEezHiw4eG/9CQeKoTpIMAdO1Ek7ILjuzV90au7G5ANtT8qQE3c7OTlVsjtzKXGG9mfYZwPaM= +Coefficient: zqyn6OSkR2j10qY+a+Yma8kiOnUdcqvk1TW8CpG9+ch9T0mlCSiB7wPkWiIqkK8fP0qVkuurIvsxEARa0FFDTZDM5g5nJ8G26LsoNj1LA8hp0xH/UB/2pSXzo1Coc3f2VAuZEunFoNxEq0XBaZm4XLbPc3cOvVeL8WmSrf2K6lU= +Created: 20130213175556 +Publish: 20130213175556 +Activate: 20130213175556 diff --git a/testing/hosts/winnetou/etc/bind/Kstrongswan.org.+008+09396.key b/testing/hosts/winnetou/etc/bind/Kstrongswan.org.+008+09396.key new file mode 100644 index 000000000..6f8eb8c70 --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/Kstrongswan.org.+008+09396.key @@ -0,0 +1,5 @@ +; This is a zone-signing key, keyid 9396, for strongswan.org. +; Created: 20130213175239 (Wed Feb 13 18:52:39 2013) +; Publish: 20130213175239 (Wed Feb 13 18:52:39 2013) +; Activate: 20130213175239 (Wed Feb 13 18:52:39 2013) +strongswan.org. IN DNSKEY 256 3 8 AwEAAa5Lb6qTxuy4ZJBDoDStnmstIU5nAsliu6UKZ6imLEg2ufAXfz7f fOtIh2/QECp80GgUDBStMvVJfRjXeJUgavM8d0Ob/rJfl1uH/buyO7Yj D+64n9t29pEuFKSAR+tYyUYk5iTidqE/CNltNkps9wc1wBAxK8ouSVXd bNvV9pvZ diff --git a/testing/hosts/winnetou/etc/bind/Kstrongswan.org.+008+09396.private b/testing/hosts/winnetou/etc/bind/Kstrongswan.org.+008+09396.private new file mode 100644 index 000000000..2a91d9106 --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/Kstrongswan.org.+008+09396.private @@ -0,0 +1,13 @@ +Private-key-format: v1.3 +Algorithm: 8 (RSASHA256) +Modulus: rktvqpPG7LhkkEOgNK2eay0hTmcCyWK7pQpnqKYsSDa58Bd/Pt9860iHb9AQKnzQaBQMFK0y9Ul9GNd4lSBq8zx3Q5v+sl+XW4f9u7I7tiMP7rif23b2kS4UpIBH61jJRiTmJOJ2oT8I2W02Smz3BzXAEDEryi5JVd1s29X2m9k= +PublicExponent: AQAB +PrivateExponent: rT8wnPZNGgnjc/60ZQha2p++ZodAHtt0N4XTKbEbfSBgzEUe52kQa3LppPvExebQ5VNf+sF6UJSesy2in2DczIqBOo2iftjKHXXWlnZN6ApN0v+oVmWxbvsEzODbeMOYklAzZd/QHvcNJCVHr+6WzxFlu5vnRwwF3vAEbFw+hIE= +Prime1: 59ugOWNLFlyOP/m7iYkr3vrei7vhT0c1IvIlBYiDSX6Ns98reI21KFXHjAl7jfx0DjJXZBK4VYCfFm7/nFS7KQ== +Prime2: wHFpgOLWd6AQfDscdkE7+rCHiaYKBADAUZ7smJni1rWFfQix+wm4qZRyrFjgT3mIZdWICJiFjh0qdrM9SvqhMQ== +Exponent1: ndmuiaOKGV1GE1QoU4ip75MINEXjLSAjkvkcL1ozV7PrMUx8wgRoE1/jDPnfvljjgk7PpHgCO2Pn61QCfiJJkQ== +Exponent2: vUKMdQIh1DIqJFNqEW7kkw5rrdcKwJcQjPUUUJv/OBP7fVVA3NfZsYVaJd+ecureVvBiwblml7ZdXbG3VPcZ8Q== +Coefficient: D6wuDQKGBlZjXQov//tXMrwhWMFhNzXfBbZCSz7td3RLspi7TJkDBFIXmJolXCLpB+Y5TNOa/3FDA8rWEIQm9w== +Created: 20130213175239 +Publish: 20130213175239 +Activate: 20130213175239 diff --git a/testing/hosts/winnetou/etc/bind/bind.keys b/testing/hosts/winnetou/etc/bind/bind.keys new file mode 100644 index 000000000..b991fa3c4 --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/bind.keys @@ -0,0 +1,46 @@ +/* $Id: bind.keys,v 1.7 2011/01/03 23:45:07 each Exp $ */ +# The bind.keys file is used to override the built-in DNSSEC trust anchors +# which are included as part of BIND 9. As of the current release, the only +# trust anchors it contains are those for the DNS root zone ("."), and for +# the ISC DNSSEC Lookaside Validation zone ("dlv.isc.org"). Trust anchors +# for any other zones MUST be configured elsewhere; if they are configured +# here, they will not be recognized or used by named. +# +# The built-in trust anchors are provided for convenience of configuration. +# They are not activated within named.conf unless specifically switched on. +# To use the built-in root key, set "dnssec-validation auto;" in +# named.conf options. To use the built-in DLV key, set +# "dnssec-lookaside auto;". Without these options being set, +# the keys in this file are ignored. +# +# This file is NOT expected to be user-configured. +# +# These keys are current as of January 2011. If any key fails to +# initialize correctly, it may have expired. In that event you should +# replace this file with a current version. The latest version of +# bind.keys can always be obtained from ISC at https://www.isc.org/bind-keys. + +managed-keys { + # ISC DLV: See https://www.isc.org/solutions/dlv for details. + # NOTE: This key is activated by setting "dnssec-lookaside auto;" + # in named.conf. + dlv.isc.org. initial-key 257 3 5 "BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWEn4MxDCE1+lLy2 + brhQv5rN32RKtMzX6Mj70jdzeND4XknW58dnJNPCxn8+jAGl2FZLK8t+ + 1uq4W+nnA3qO2+DL+k6BD4mewMLbIYFwe0PG73Te9fZ2kJb56dhgMde5 + ymX4BI/oQ+cAK50/xvJv00Frf8kw6ucMTwFlgPe+jnGxPPEmHAte/URk + Y62ZfkLoBAADLHQ9IrS2tryAe7mbBZVcOwIeU/Rw/mRx/vwwMCTgNboM + QKtUdvNXDrYJDSHZws3xiRXF1Rf+al9UmZfSav/4NWLKjHzpT59k/VSt + TDN0YUuWrBNh"; + + # ROOT KEY: See https://data.iana.org/root-anchors/root-anchors.xml + # for current trust anchor information. + # NOTE: This key is activated by setting "dnssec-validation auto;" + # in named.conf. + . initial-key 257 3 8 "AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2 + XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b + L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx + E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b + AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5 + nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO + O9fOgGnjzAk="; +}; diff --git a/testing/hosts/winnetou/etc/bind/db.org b/testing/hosts/winnetou/etc/bind/db.org new file mode 100644 index 000000000..ecd2c23c1 --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/db.org @@ -0,0 +1,40 @@ +; +; Zonefile for the org zone +; +$TTL 604800 +@ IN SOA ns1.org. root.org. ( + 1 ; Serial + 604800 ; Refresh + 86400 ; Retry + 2419200 ; Expire + 604800 ) ; Negative Cache TTL +; +@ IN NS ns1.org. +ns1 IN A 192.168.0.150 +ns1 IN AAAA fe80::fcfd:c0ff:fea8:96 +; +strongswan IN NS ns1.strongswan.org. +ns1.strongswan IN A 192.168.0.150 +ns1.strongswan IN AAAA fe80::fcfd:c0ff:fea8:96 +; +strongswan.org. IN DS 481 8 1 5B239B124E38890C1853F5ECF299DEDEB5537E55 +strongswan.org. IN DS 481 8 2 FEE6842CA2322347D818318D278A929E0B9FD82353B84AE94A6A4C7B 1DFB4FEE +; +; This is a zone-signing key, keyid 24285, for org. +org. IN DNSKEY 256 3 8 ( + AwEAAa6IO30MFlgyj0hJLe0vqvHLr1/4kRCNl/Biz7VYwgzRkiYxHxLJ + U+i8/r9rEWU85Q6WEt77xQ+HyxzwmoXpSaMtymYifNFZnvwl31CbkzIB + FTtBUQ3BCKZjv0WgpLExDqAKgclCWBZ1PrHvDn1HTl6mMgCpiWothzkn + zoNbB0g9 + ) +; +; This is a key-signing key, keyid 51859, for org. +org. IN DNSKEY 257 3 8 ( + AwEAAfAyiINF1/fIyebiAZhG3kFxv1+j3D3TxNBPccbiVUgYSnse95mb + mn40KgguCljoi6kDu10Qo+XUwpR78dGJiqvKfej7cz6wbIr5qu9Kv7f8 + lJPRQ2igxZ/0ZCLXGbozRuQGy39klQeG98fwxNkzHqXRxkhyAgpY8E2B + umRsi2Cca/vKF+6OpNx9b8RXIBcUTdhx0Vjg+3gYhSRR1rPB160sbaL+ + v3Fxv9ZzOIY9ekforNxuqV9/U0DCiOhgpZC7H+5ShPb0VNzYvv0IwIAG + VPVEJdh5SNPQ0LclPXcR3av+DpjvdY5oAOn/mLPCHjxBnzOl7Q3P43dL + DtYdKb9mGnk= + ) diff --git a/testing/hosts/winnetou/etc/bind/db.root b/testing/hosts/winnetou/etc/bind/db.root new file mode 100644 index 000000000..cfbbbc8bf --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/db.root @@ -0,0 +1,40 @@ +; +; Zonefile for the root zone +; +$TTL 604800 +@ IN SOA ns1. root. ( + 1 ; Serial + 604800 ; Refresh + 86400 ; Retry + 2419200 ; Expire + 604800 ) ; Negative Cache TTL +; +@ IN NS ns1. +ns1 IN A 192.168.0.150 +ns1 IN AAAA fe80::fcfd:c0ff:fea8:96 +; +org IN NS ns1.org. +ns1.org IN A 192.168.0.150 +ns1.org IN AAAA fe80::fcfd:c0ff:fea8:96 +; +org. IN DS 51859 8 1 5075E7B1185CFCC744364EC45D2E03CBA6178929 +org. IN DS 51859 8 2 9122D2557F70A8CE5CB14E85BF5D966848FC7016A0E2E021012F33B8 398770A9 +; +; This is a zone-signing key, keyid 43749, for . +. IN DNSKEY 256 3 8 ( + AwEAAdMS+CyW9m8yB6rwrqsdfMW41AWim1T/ehg4Un/9qADFEZN9T7NK + 9PI+DD3Dr72Z2ZO4hrKXB2Xe0nlvsCUjTfCwdGqgz9YLv2WfXzqRksxF + gQXmzAdG7JGH+7YmXq7AAF3246caa+wMXAGRdUUCiQf87CnAaZXJ1kUz + wHw3Arp5 + ) +; +; This is a key-signing key, keyid 32329, for . +. IN DNSKEY 257 3 8 ( + AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2 + XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b + L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx + E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b + AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5 + nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO + O9fOgGnjzAk= + ) diff --git a/testing/hosts/winnetou/etc/bind/db.strongswan.org b/testing/hosts/winnetou/etc/bind/db.strongswan.org new file mode 100644 index 000000000..dfd2705cb --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/db.strongswan.org @@ -0,0 +1,88 @@ +; +; Zonefile for the strongswan.org zone +; +$TTL 604800 +@ IN SOA ns1.strongswan.org. root.strongswan.org. ( + 1 ; Serial + 604800 ; Refresh + 86400 ; Retry + 2419200 ; Expire + 604800 ) ; Negative Cache TTL +; +@ IN NS ns1.strongswan.org. +ns1 IN A 192.168.0.150 +ns1 IN AAAA fe80::fcfd:c0ff:fea8:96 +; +moon IN A 192.168.0.1 +sun IN A 192.168.0.2 +mars IN A 192.168.0.5 +alice1 IN A 192.168.0.50 +carol IN A 192.168.0.100 +winnetou IN A 192.168.0.150 +dave IN A 192.168.0.200 +; +ip6-moon IN AAAA fe80::fcfd:c0ff:fea8:01 +ip6-sun IN AAAA fe80::fcfd:c0ff:fea8:02 +ip6-carol IN AAAA fe80::fcfd:c0ff:fea8:64 +ip6-winnetou IN AAAA fe80::fcfd:c0ff:fea8:96 +ip6-dave IN AAAA fe80::fcfd:c0ff:fea8:c8 +; +crl IN CNAME winnetou.strongswan.org. +ldap IN CNAME winnetou.strongswan.org. +ocsp IN CNAME winnetou.strongswan.org. +; +moon IN IPSECKEY ( 10 1 2 192.168.0.1 + AwEAAcovYz3Uu7oFhiFbFaAxL3P1MxJPCzObmuE7tkiwK0xGjg8B5jD7 + 75IZe3cI9dv/6n5JYoaWbXWs8TvV5Dd6GCHYLeEC6t+ZY7SJBBoLD592 + t54hUKo5Ag4/pSpnfbuHnJhikeTxVC/i8ElOnFyVTU+qdaF6p7VmUvGx + bvvctGaX99C39SC8mQIFNlk40s0x8r7tMOdhpWwC2dyC8M3vydQ0R7ap + j3YortKsEnpKlQSDj2bnUX5eCwZyyBZUdLzmifc6b8bjxyssRUmN27w + LF7BJFWBv6U8lbMd3xCxTRWD/u+WqzdlEzI200quviilK9VsDpqAaVNe + EMKt4OJdTwoc= + ) +sun IN IPSECKEY ( 10 1 2 192.168.0.2 + AwEAAd+VVIpn6Q5jaU//EN6p6A5cSfUfhBK0mFa2laFFZh/Y0h66AXqq + rQ3X917h7YNsSk68oowY9h9I3gOx7hNVBsJr2VjdYC+b0q5NTha09/A5 + mimv/prYj6o0yawxoPjoDs9Yh7D7Kf+F8fkgk0stlHJZX66J7dNrFXbg + 1xBld+Ep5Or2FbEZ9QWUpRQTuhdpNt/49YuxQ59DemY9IRbwsrKCHH0m + GrJsDdqeb0ap+8QvSXHjCt1fr9MNKWaAFAQLKQI4e0da1ntPCEQLeE83 + 3+NNRBgGufk0KqGT3eAXqrxa9AEIUJnVcPexQdqUMjcUpXFb8WNzRWB8 + Egh3BDK6FsE= + ) +carol IN IPSECKEY ( 10 1 2 192.168.0.100 + AwEAAdBdWU+BF7x4lyo+xHnr4UAOU89yQQuT5vdPoXzx6kRPsjYAuukt + gXR+SaLkQHw/YRgDPSKj5nzmmlOQf/rWRr+8O2q+C92aUICmkNvZGamo + 5w2WlOMZ6T5dk2Hv+QM6xT/GzWyVr1dMYu/7tywD1Bw7aW/HqkRESDu6 + q95VWu+Lzg6XlxCNEez0YsZrN/fC6BL2qzKAqMBbIHFW8OOnh+nEY4IF + 5AzkZnFrw12GI72Z882pw97lyKwZhSz/GMQFBJx+rnNdw5P1IJwTlG5P + UdoDCte/Mcr1iiA+zOovx55x1GoGxduoXWU5egrf1MtalRf9Pc8Xr4q3 + WEKTAmsZrVE= + ) +dave IN IPSECKEY ( 10 1 2 192.168.0.200 + AwEAAcAH8lNvBVjmg0XT7wF6F1tzQ055f5uXRI5yClmFrqdswFA7jWO0 + 4jmvlduD2wr2X4Ng6dlBkSwSEhVkOgrzIYj8UgQT6BZF/44uYjyTYr4b + V2SVML9U/a1lYxBhBazpSdfeKJWkdxwjcJCqolZ719mwiyrQn2P2G7qH + 10YgRuifpFcMs8jkMiIgpzevSMMc0OwhQPNyO5R0LEoUIy4dQJ9rU8GK + qmPmk/pdPQaAjpSNuCc1Y9M9vZrETs/XHmBCZXCIWJiz5VOHZ+r073E3 + Gef9ibMuTj9g2XLvFhdDfU26FK9GkfuOwnWnhVK66diq9xw9Qqynk+8K + 0J4a81Paq3U= + ) +; +; This is a zone-signing key, keyid 9396, for strongswan.org. +strongswan.org. IN DNSKEY 256 3 8 ( + AwEAAa5Lb6qTxuy4ZJBDoDStnmstIU5nAsliu6UKZ6imLEg2ufAXfz7f + fOtIh2/QECp80GgUDBStMvVJfRjXeJUgavM8d0Ob/rJfl1uH/buyO7Yj + D+64n9t29pEuFKSAR+tYyUYk5iTidqE/CNltNkps9wc1wBAxK8ouSVXd + bNvV9pvZ + ) +; +; This is a key-signing key, keyid 481, for strongswan.org. +strongswan.org. IN DNSKEY 257 3 8 ( + AwEAAcXfcWvCGzQq80q9JX1Wvz0lwA/fi1XZmega350wGR8WdFCklvmK + fAzNaf1CrvN3bH9Gl2VEEhkYMF6h6kVFTU7taspq5t0bLwgCK/nS8QzK + TLWvzWdyVayiHfij1PPwnQV5FADBTE5mMEkmn82+PKg6jaKs3ANsc0BP + bGSsGIxhUKliLxJEd+6KSl/+ouQD9RfCD5sz9NIF+IXv1ZGp2Rjf+6vK + bPO8f0hmttwE/OzKyBgysLBbd6fw2pKOBhunVFmUYPaHM9zLTydzuSIA + X9iSeM6HtAvlKgK0JGgPEFrX+jPG6wDvJfzzakx85rMkRGc31NFiFLqM + ooWxy1674/U= + ) diff --git a/testing/hosts/winnetou/etc/bind/named.conf.default-zones b/testing/hosts/winnetou/etc/bind/named.conf.default-zones new file mode 100644 index 000000000..52a1e4c7c --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/named.conf.default-zones @@ -0,0 +1,23 @@ +// be authoritative for the localhost forward and reverse zones, and for +// broadcast zones as per RFC 1912 + +zone "localhost" { + type master; + file "/etc/bind/db.local"; +}; + +zone "127.in-addr.arpa" { + type master; + file "/etc/bind/db.127"; +}; + +zone "0.in-addr.arpa" { + type master; + file "/etc/bind/db.0"; +}; + +zone "255.in-addr.arpa" { + type master; + file "/etc/bind/db.255"; +}; + diff --git a/testing/hosts/winnetou/etc/bind/named.conf.local b/testing/hosts/winnetou/etc/bind/named.conf.local new file mode 100644 index 000000000..fa26fa9e5 --- /dev/null +++ b/testing/hosts/winnetou/etc/bind/named.conf.local @@ -0,0 +1,18 @@ +// +// Do any local configuration here +// + +zone "." { + type master; + file "/etc/bind/db.root.signed"; +}; + +zone "org" { + type master; + file "/etc/bind/db.org.signed"; +}; + +zone "strongswan.org" { + type master; + file "/etc/bind/db.strongswan.org.signed"; +}; diff --git a/testing/scripts/build-baseimage b/testing/scripts/build-baseimage index 1355d7a05..684730ced 100755 --- a/testing/scripts/build-baseimage +++ b/testing/scripts/build-baseimage @@ -15,8 +15,8 @@ INC=build-essential,gperf,libgmp-dev,libldap2-dev,libcurl4-openssl-dev,ethtool INC=$INC,libxml2-dev,libtspi-dev,libsqlite3-dev,openssh-server,tcpdump,psmisc INC=$INC,openssl,vim,sqlite3,conntrack,gdb,cmake,libxerces-c2-dev,libltdl-dev INC=$INC,liblog4cxx10-dev,libboost-thread-dev,libboost-system-dev,git-core -INC=$INC,less,acpid,acpi-support-base -SERVICES="apache2 dbus isc-dhcp-server slapd" +INC=$INC,less,acpid,acpi-support-base,libldns-dev,libunbound-dev,dnsutils,screen +SERVICES="apache2 dbus isc-dhcp-server slapd bind9" INC=$INC,${SERVICES// /,} EXC=iptables @@ -67,6 +67,9 @@ do_on_exit graceful_umount $APTCACHE log_action "Running debootstrap ($BASEIMGSUITE, $BASEIMGARCH)" execute "debootstrap --arch=$BASEIMGARCH --include=$INC --exclude $EXC $BASEIMGSUITE $LOOPDIR $BASEIMGMIRROR" +execute "mount -t proc none $LOOPDIR/proc" +do_on_exit graceful_umount $LOOPDIR/proc + for service in $SERVICES do log_action "Stopping service $service" diff --git a/testing/scripts/build-guestimages b/testing/scripts/build-guestimages index f5669040e..3e0709db9 100755 --- a/testing/scripts/build-guestimages +++ b/testing/scripts/build-guestimages @@ -57,6 +57,10 @@ do execute_chroot "rm -rf /var/lib/ldap/*" 0 execute_chroot "slapadd -l /etc/ldap/ldif.txt -f /etc/ldap/slapd.conf" 0 execute_chroot "chown -R openldap:openldap /var/lib/ldap" 0 + execute_chroot "dnssec-signzone -K /etc/bind -o strongswan.org. /etc/bind/db.strongswan.org" 0 + execute_chroot "dnssec-signzone -K /etc/bind -o org. /etc/bind/db.org" 0 + execute_chroot "dnssec-signzone -K /etc/bind -o . /etc/bind/db.root" 0 + execute_chroot "update-rc.d bind9 defaults" 0 fi sync execute "umount $LOOPDIR" 0 diff --git a/testing/scripts/recipes/005_strongswan.mk b/testing/scripts/recipes/005_strongswan.mk index 76d2d0882..8bac5aa07 100644 --- a/testing/scripts/recipes/005_strongswan.mk +++ b/testing/scripts/recipes/005_strongswan.mk @@ -67,7 +67,9 @@ CONFIG_OPTS = \ --enable-xauth-generic \ --enable-xauth-eap \ --enable-pkcs8 \ - --enable-unity + --enable-unity \ + --enable-unbound \ + --enable-ipseckey all: install diff --git a/testing/ssh b/testing/ssh new file mode 100755 index 000000000..4777cfb47 --- /dev/null +++ b/testing/ssh @@ -0,0 +1,36 @@ +#!/bin/bash + +DIR=$(dirname `readlink -f $0`) +. $DIR/testing.conf + +if [ $# == 0 ] +then + echo "$0 <host>" + exit 1 +fi + +host=$1 +echo "$host" | grep -q "^\([0-9]\+\.\|[0-9a-fA-F]\+:\).*" +if [ $? -eq 0 ] +then + # assume we got an ip address + ip=$host +else + pos='$1' + echo "$host" | grep -q ".*1$" + if [ $? -eq 0 ] + then + # {host}1, use second address + pos='$2' + host=`echo "$host" | sed -n -e "s/1$//p"` + fi + ip="`echo $HOSTNAMEIPV4 | sed -n -e "s/^.*${host},//gp" | awk -F, "{ print ${pos} }" | awk '{ print $1 }'`" + if [ -z $ip ] + then + echo "Host '$host' unknown" + exit 1 + fi +fi + +shift +exec ssh $SSHCONF -q root@$ip $@ diff --git a/testing/start-testing b/testing/start-testing index 183729423..db582cfd7 100755 --- a/testing/start-testing +++ b/testing/start-testing @@ -15,7 +15,7 @@ echo "Starting test environment" [ `id -u` -eq 0 ] || die "You must be root to run $0" -check_commands virsh +check_commands kvm virsh log_action "Deploying kernel $KERNEL" execute "ln -fs $KNLSRC $KNLTARGET" diff --git a/testing/testing.conf b/testing/testing.conf index 960d3f63e..89552de9c 100644 --- a/testing/testing.conf +++ b/testing/testing.conf @@ -18,14 +18,14 @@ TESTDIR=/srv/strongswan-testing # Kernel configuration -KERNELVERSION=3.5.3 +KERNELVERSION=3.8.1 KERNEL=linux-$KERNELVERSION KERNELTARBALL=$KERNEL.tar.bz2 -KERNELCONFIG=$DIR/../config/kernel/config-3.5 -KERNELPATCH=ha-3.0.patch.bz2 +KERNELCONFIG=$DIR/../config/kernel/config-3.8 +KERNELPATCH=ha-3.8.patch.bz2 # strongSwan version used in tests -SWANVERSION=5.0.2dr4 +SWANVERSION=5.0.3 # Build directory where the guest kernel and images will be built BUILDDIR=$TESTDIR/build diff --git a/testing/tests/ikev1/net2net-fragmentation/description.txt b/testing/tests/ikev1/net2net-fragmentation/description.txt new file mode 100644 index 000000000..6fe773299 --- /dev/null +++ b/testing/tests/ikev1/net2net-fragmentation/description.txt @@ -0,0 +1,9 @@ +A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up. +The authentication is based on <b>X.509 certificates</b>. The proprietary IKEv1 fragmentation +protocol prevents the IP fragmentation of the IKEv1 messages carrying the large X.509 +certificates. +<p/> +Upon the successful establishment of the IPsec tunnel, <b>leftfirewall=yes</b> automatically +inserts iptables-based firewall rules that let pass the tunneled traffic. +In order to test both tunnel and firewall, client <b>alice</b> behind gateway <b>moon</b> +pings client <b>bob</b> located behind gateway <b>sun</b>. diff --git a/testing/tests/ikev1/net2net-fragmentation/evaltest.dat b/testing/tests/ikev1/net2net-fragmentation/evaltest.dat new file mode 100644 index 000000000..876787495 --- /dev/null +++ b/testing/tests/ikev1/net2net-fragmentation/evaltest.dat @@ -0,0 +1,15 @@ +moon::cat /var/log/daemon.log::received FRAGMENTATION vendor ID::YES +sun::cat /var/log/daemon.log::received FRAGMENTATION vendor ID::YES +moon::cat /var/log/daemon.log::sending IKE message with length of 1468 bytes in 2 fragments::YES +sun::cat /var/log/daemon.log::sending IKE message with length of 1388 bytes in 2 fragments::YES +moon::cat /var/log/daemon.log::received fragment #1, waiting for complete IKE message::YES +moon::cat /var/log/daemon.log::received fragment #2, reassembling fragmented IKE message::YES +sun::cat /var/log/daemon.log::received fragment #1, waiting for complete IKE message::YES +sun::cat /var/log/daemon.log::received fragment #2, reassembling fragmented IKE message::YES +moon::ipsec status 2> /dev/null::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES +sun:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES +moon::ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES +sun:: ipsec status 2> /dev/null::net-net.*INSTALLED, TUNNEL::YES +alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES +sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES +sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES diff --git a/testing/tests/ikev1/net2net-fragmentation/hosts/moon/etc/ipsec.conf b/testing/tests/ikev1/net2net-fragmentation/hosts/moon/etc/ipsec.conf new file mode 100644 index 000000000..cdd430408 --- /dev/null +++ b/testing/tests/ikev1/net2net-fragmentation/hosts/moon/etc/ipsec.conf @@ -0,0 +1,22 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + keyexchange=ikev1 + fragmentation=yes + +conn net-net + left=PH_IP_MOON + leftcert=moonCert.pem + leftid=@moon.strongswan.org + leftsubnet=10.1.0.0/16 + leftfirewall=yes + right=PH_IP_SUN + rightid=@sun.strongswan.org + rightsubnet=10.2.0.0/16 + auto=add diff --git a/testing/tests/ikev1/net2net-fragmentation/hosts/moon/etc/strongswan.conf b/testing/tests/ikev1/net2net-fragmentation/hosts/moon/etc/strongswan.conf new file mode 100644 index 000000000..9caf4fa37 --- /dev/null +++ b/testing/tests/ikev1/net2net-fragmentation/hosts/moon/etc/strongswan.conf @@ -0,0 +1,11 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default updown + + fragment_size = 1024 +} + +libstrongswan { + dh_exponent_ansi_x9_42 = no +} diff --git a/testing/tests/ikev1/net2net-fragmentation/hosts/sun/etc/ipsec.conf b/testing/tests/ikev1/net2net-fragmentation/hosts/sun/etc/ipsec.conf new file mode 100644 index 000000000..448525bf7 --- /dev/null +++ b/testing/tests/ikev1/net2net-fragmentation/hosts/sun/etc/ipsec.conf @@ -0,0 +1,22 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + keyexchange=ikev1 + fragmentation=yes + +conn net-net + left=PH_IP_SUN + leftcert=sunCert.pem + leftid=@sun.strongswan.org + leftsubnet=10.2.0.0/16 + leftfirewall=yes + right=PH_IP_MOON + rightid=@moon.strongswan.org + rightsubnet=10.1.0.0/16 + auto=add diff --git a/testing/tests/ikev1/net2net-fragmentation/hosts/sun/etc/strongswan.conf b/testing/tests/ikev1/net2net-fragmentation/hosts/sun/etc/strongswan.conf new file mode 100644 index 000000000..9caf4fa37 --- /dev/null +++ b/testing/tests/ikev1/net2net-fragmentation/hosts/sun/etc/strongswan.conf @@ -0,0 +1,11 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default updown + + fragment_size = 1024 +} + +libstrongswan { + dh_exponent_ansi_x9_42 = no +} diff --git a/testing/tests/ikev1/net2net-fragmentation/posttest.dat b/testing/tests/ikev1/net2net-fragmentation/posttest.dat new file mode 100644 index 000000000..837738fc6 --- /dev/null +++ b/testing/tests/ikev1/net2net-fragmentation/posttest.dat @@ -0,0 +1,5 @@ +moon::ipsec stop +sun::ipsec stop +moon::iptables-restore < /etc/iptables.flush +sun::iptables-restore < /etc/iptables.flush + diff --git a/testing/tests/ikev1/net2net-fragmentation/pretest.dat b/testing/tests/ikev1/net2net-fragmentation/pretest.dat new file mode 100644 index 000000000..c724e5df8 --- /dev/null +++ b/testing/tests/ikev1/net2net-fragmentation/pretest.dat @@ -0,0 +1,6 @@ +moon::iptables-restore < /etc/iptables.rules +sun::iptables-restore < /etc/iptables.rules +moon::ipsec start +sun::ipsec start +moon::sleep 1 +moon::ipsec up net-net diff --git a/testing/tests/ikev1/net2net-fragmentation/test.conf b/testing/tests/ikev1/net2net-fragmentation/test.conf new file mode 100644 index 000000000..646b8b3e6 --- /dev/null +++ b/testing/tests/ikev1/net2net-fragmentation/test.conf @@ -0,0 +1,21 @@ +#!/bin/bash +# +# This configuration file provides information on the +# guest instances used for this test + +# All guest instances that are required for this test +# +VIRTHOSTS="alice moon winnetou sun bob" + +# Corresponding block diagram +# +DIAGRAM="a-m-w-s-b.png" + +# Guest instances on which tcpdump is to be started +# +TCPDUMPHOSTS="sun" + +# Guest instances on which IPsec is started +# Used for IPsec logging purposes +# +IPSECHOSTS="moon sun" diff --git a/testing/tests/ikev2/net2net-dnssec/description.txt b/testing/tests/ikev2/net2net-dnssec/description.txt new file mode 100644 index 000000000..9893359c0 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/description.txt @@ -0,0 +1,8 @@ +A connection between the subnets behind the gateways <b>moon</b> and <b>sun</b> is set up. +The authentication is based on trustworthy public keys stored as <b>IPSECKEY</b> +resource records in the Domain Name System (DNS) and protected by <b>DNSSEC</b>. +<p/> +Upon the successful establishment of the IPsec tunnel, <b>leftfirewall=yes</b> +automatically inserts iptables-based firewall rules that let pass the tunneled traffic. +In order to test both tunnel and firewall, client <b>alice</b> behind gateway <b>moon</b> +pings client <b>bob</b> located behind gateway <b>sun</b>. diff --git a/testing/tests/ikev2/net2net-dnssec/evaltest.dat b/testing/tests/ikev2/net2net-dnssec/evaltest.dat new file mode 100644 index 000000000..389cac7f3 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/evaltest.dat @@ -0,0 +1,9 @@ +moon:: cat /var/log/daemon.log::performing a DNS query for IPSECKEY RRs of.*sun.strongswan.org::YES +sun:: cat /var/log/daemon.log::performing a DNS query for IPSECKEY RRs of.*moon.strongswan.org::YES +moon:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*moon.strongswan.org.*sun.strongswan.org::YES +sun:: ipsec status 2> /dev/null::net-net.*ESTABLISHED.*sun.strongswan.org.*moon.strongswan.org::YES +moon:: ipsec status 2> /dev/null::INSTALLED, TUNNEL::YES +sun:: ipsec status 2> /dev/null::INSTALLED, TUNNEL::YES +alice::ping -c 1 PH_IP_BOB::64 bytes from PH_IP_BOB: icmp_req=1::YES +sun::tcpdump::IP moon.strongswan.org > sun.strongswan.org: ESP::YES +sun::tcpdump::IP sun.strongswan.org > moon.strongswan.org: ESP::YES diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.conf new file mode 100644 index 000000000..6c11645f9 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.conf @@ -0,0 +1,24 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + keyexchange=ikev2 + mobike=no + +conn net-net + left=PH_IP_MOON + leftid=moon.strongswan.org + leftsubnet=10.1.0.0/16 + leftrsasigkey=moonPub.der + leftauth=pubkey + leftfirewall=yes + right=sun.strongswan.org + rightid=sun.strongswan.org + rightsubnet=10.2.0.0/16 + rightauth=pubkey + auto=add diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.d/certs/moonPub.der b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.d/certs/moonPub.der Binary files differnew file mode 100644 index 000000000..71571044c --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.d/certs/moonPub.der diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.d/dnssec.keys b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.d/dnssec.keys new file mode 100644 index 000000000..d059d8476 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/ipsec.d/dnssec.keys @@ -0,0 +1,10 @@ +; This is a key-signing key, keyid 32329, for . +. IN DNSKEY 257 3 8 ( + AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2 + XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b + L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx + E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b + AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5 + nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO + O9fOgGnjzAk= + ) diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/iptables.rules b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/iptables.rules new file mode 100644 index 000000000..b2c425289 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/iptables.rules @@ -0,0 +1,28 @@ +*filter + +# default policy is DROP +-P INPUT DROP +-P OUTPUT DROP +-P FORWARD DROP + +# allow esp +-A INPUT -i eth0 -p 50 -j ACCEPT +-A OUTPUT -o eth0 -p 50 -j ACCEPT + +# allow IKE +-A INPUT -i eth0 -p udp --sport 500 --dport 500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 500 --sport 500 -j ACCEPT + +# allow MobIKE +-A INPUT -i eth0 -p udp --sport 4500 --dport 4500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 4500 --sport 4500 -j ACCEPT + +# allow ssh +-A INPUT -p tcp --dport 22 -j ACCEPT +-A OUTPUT -p tcp --sport 22 -j ACCEPT + +# allow DNSSEC fetch from winnetou +-A INPUT -i eth0 -p udp --sport 53 -s PH_IP_WINNETOU -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 53 -d PH_IP_WINNETOU -j ACCEPT + +COMMIT diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/resolv.conf b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/resolv.conf new file mode 100644 index 000000000..73d926def --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/resolv.conf @@ -0,0 +1 @@ +nameserver PH_IP_WINNETOU diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/strongswan.conf new file mode 100644 index 000000000..44a54a9dd --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/hosts/moon/etc/strongswan.conf @@ -0,0 +1,20 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = sha1 sha2 md5 aes des hmac gmp dnskey pem pkcs1 pubkey unbound ipseckey random nonce curl kernel-netlink socket-default stroke updown + + plugins { + ipseckey { + enable = yes + } + } +} + +libstrongswan { + plugins { + unbound { + # trust_anchors = /etc/ipsec.d/dnssec.keys + # resolv_conf = /etc/resolv.conf + } + } +} diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.conf b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.conf new file mode 100644 index 000000000..76e41cd47 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.conf @@ -0,0 +1,24 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + keyexchange=ikev2 + mobike=no + +conn net-net + left=PH_IP_SUN + leftid=sun.strongswan.org + leftsubnet=10.2.0.0/16 + leftrsasigkey=sunPub.der + leftauth=pubkey + leftfirewall=yes + right=moon.strongswan.org + rightid=moon.strongswan.org + rightsubnet=10.1.0.0/16 + rightauth=pubkey + auto=add diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.d/certs/sunPub.der b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.d/certs/sunPub.der Binary files differnew file mode 100644 index 000000000..cc99934db --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.d/certs/sunPub.der diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.d/dnssec.keys b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.d/dnssec.keys new file mode 100644 index 000000000..d059d8476 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/ipsec.d/dnssec.keys @@ -0,0 +1,10 @@ +; This is a key-signing key, keyid 32329, for . +. IN DNSKEY 257 3 8 ( + AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2 + XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b + L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx + E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b + AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5 + nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO + O9fOgGnjzAk= + ) diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/iptables.rules b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/iptables.rules new file mode 100644 index 000000000..b2c425289 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/iptables.rules @@ -0,0 +1,28 @@ +*filter + +# default policy is DROP +-P INPUT DROP +-P OUTPUT DROP +-P FORWARD DROP + +# allow esp +-A INPUT -i eth0 -p 50 -j ACCEPT +-A OUTPUT -o eth0 -p 50 -j ACCEPT + +# allow IKE +-A INPUT -i eth0 -p udp --sport 500 --dport 500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 500 --sport 500 -j ACCEPT + +# allow MobIKE +-A INPUT -i eth0 -p udp --sport 4500 --dport 4500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 4500 --sport 4500 -j ACCEPT + +# allow ssh +-A INPUT -p tcp --dport 22 -j ACCEPT +-A OUTPUT -p tcp --sport 22 -j ACCEPT + +# allow DNSSEC fetch from winnetou +-A INPUT -i eth0 -p udp --sport 53 -s PH_IP_WINNETOU -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 53 -d PH_IP_WINNETOU -j ACCEPT + +COMMIT diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/resolv.conf b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/resolv.conf new file mode 100644 index 000000000..73d926def --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/resolv.conf @@ -0,0 +1 @@ +nameserver PH_IP_WINNETOU diff --git a/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/strongswan.conf b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/strongswan.conf new file mode 100644 index 000000000..44a54a9dd --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/hosts/sun/etc/strongswan.conf @@ -0,0 +1,20 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = sha1 sha2 md5 aes des hmac gmp dnskey pem pkcs1 pubkey unbound ipseckey random nonce curl kernel-netlink socket-default stroke updown + + plugins { + ipseckey { + enable = yes + } + } +} + +libstrongswan { + plugins { + unbound { + # trust_anchors = /etc/ipsec.d/dnssec.keys + # resolv_conf = /etc/resolv.conf + } + } +} diff --git a/testing/tests/ikev2/net2net-dnssec/posttest.dat b/testing/tests/ikev2/net2net-dnssec/posttest.dat new file mode 100644 index 000000000..c594c4dc8 --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/posttest.dat @@ -0,0 +1,8 @@ +moon::ipsec stop +sun::ipsec stop +moon::iptables-restore < /etc/iptables.flush +sun::iptables-restore < /etc/iptables.flush +moon::rm /etc/resolv.conf +sun::rm /etc/resolv.conf +moon::rm /etc/ipsec.d/dnssec.keys +sun::rm /etc/ipsec.d/dnssec.keys diff --git a/testing/tests/ikev2/net2net-dnssec/pretest.dat b/testing/tests/ikev2/net2net-dnssec/pretest.dat new file mode 100644 index 000000000..0f4ae0f4f --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/pretest.dat @@ -0,0 +1,8 @@ +moon::iptables-restore < /etc/iptables.rules +sun::iptables-restore < /etc/iptables.rules +moon::rm /etc/ipsec.d/cacerts/* +sun::rm /etc/ipsec.d/cacerts/* +moon::ipsec start +sun::ipsec start +moon::sleep 2 +moon::ipsec up net-net diff --git a/testing/tests/ikev2/net2net-dnssec/test.conf b/testing/tests/ikev2/net2net-dnssec/test.conf new file mode 100644 index 000000000..afa2accbe --- /dev/null +++ b/testing/tests/ikev2/net2net-dnssec/test.conf @@ -0,0 +1,21 @@ +#!/bin/bash +# +# This configuration file provides information on the +# guest instances used for this test + +# All guest instances that are required for this test +# +VIRTHOSTS="alice moon winnetou sun bob" + +# Corresponding block diagram +# +DIAGRAM="a-m-w-s-b.png" + +# Guest instances on which tcpdump is to be started +# +TCPDUMPHOSTS="sun" + +# Guest instances on which IPsec is started +# Used for IPsec logging purposes +# +IPSECHOSTS="moon sun" diff --git a/testing/tests/ikev2/rw-dnssec/description.txt b/testing/tests/ikev2/rw-dnssec/description.txt new file mode 100644 index 000000000..0135f078c --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/description.txt @@ -0,0 +1,10 @@ +The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gateway <b>moon</b>. +The authentication is based on trustworthy public keys stored as <b>IPSECKEY</b> +resource records in the Domain Name System (DNS) and protected by <b>DNSSEC</b>. +</p> +Both <b>carol</b> and <b>dave</b> request a <b>virtual IP</b> via the IKEv2 configuration payload +by using the <b>leftsourceip=%config</b> parameter. <b>leftfirewall=yes</b> automatically +inserts iptables-based firewall rules that let pass the tunneled traffic. In order to test the +tunnels, <b>carol</b> and <b>dave</b> then ping the client <b>alice</b> behind the gateway +<b>moon</b>. The source IP addresses of the two pings will be the virtual IPs <b>carol1</b> +and <b>dave1</b>, respectively. diff --git a/testing/tests/ikev2/rw-dnssec/evaltest.dat b/testing/tests/ikev2/rw-dnssec/evaltest.dat new file mode 100644 index 000000000..49183fb42 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/evaltest.dat @@ -0,0 +1,24 @@ +carol::cat /var/log/daemon.log::performing a DNS query for IPSECKEY RRs of.*moon.strongswan.org::YES +carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol.strongswan.org.*moon.strongswan.org::YES +carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES +carol::cat /var/log/daemon.log::installing new virtual IP PH_IP_CAROL1::YES +carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES +dave:: cat /var/log/daemon.log::performing a DNS query for IPSECKEY RRs of.*moon.strongswan.org::YES +dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave.strongswan.org.*moon.strongswan.org::YES +dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES +dave:: cat /var/log/daemon.log::installing new virtual IP PH_IP_DAVE1::YES +dave:: ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES +moon:: cat /var/log/daemon.log::performing a DNS query for IPSECKEY RRs of.*carol.strongswan.org::YES +moon:: cat /var/log/daemon.log::performing a DNS query for IPSECKEY RRs of.*dave.strongswan.org::YES +moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol.strongswan.org::YES +moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave.strongswan.org::YES +moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES +moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES +moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP::YES +moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP::YES +moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP::YES +moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP::YES +alice::tcpdump::IP carol1.strongswan.org > alice.strongswan.org: ICMP echo request::YES +alice::tcpdump::IP alice.strongswan.org > carol1.strongswan.org: ICMP echo reply::YES +alice::tcpdump::IP dave1.strongswan.org > alice.strongswan.org: ICMP echo request::YES +alice::tcpdump::IP alice.strongswan.org > dave1.strongswan.org: ICMP echo reply::YES diff --git a/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.conf b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.conf new file mode 100644 index 000000000..70deaa036 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.conf @@ -0,0 +1,23 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + keyexchange=ikev2 + +conn home + left=%any + leftsourceip=%config + leftid=carol.strongswan.org + leftrsasigkey="0sAwEAAdBdWU+BF7x4lyo+xHnr4UAOU89yQQuT5vdPoXzx6kRPsjYAuuktgXR+SaLkQHw/YRgDPSKj5nzmmlOQf/rWRr+8O2q+C92aUICmkNvZGamo5w2WlOMZ6T5dk2Hv+QM6xT/GzWyVr1dMYu/7tywD1Bw7aW/HqkRESDu6q95VWu+Lzg6XlxCNEez0YsZrN/fC6BL2qzKAqMBbIHFW8OOnh+nEY4IF5AzkZnFrw12GI72Z882pw97lyKwZhSz/GMQFBJx+rnNdw5P1IJwTlG5PUdoDCte/Mcr1iiA+zOovx55x1GoGxduoXWU5egrf1MtalRf9Pc8Xr4q3WEKTAmsZrVE=" + leftauth=pubkey + leftfirewall=yes + right=moon.strongswan.org + rightid=moon.strongswan.org + rightsubnet=10.1.0.0/16 + rightauth=pubkey + auto=add diff --git a/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.d/dnssec.keys b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.d/dnssec.keys new file mode 100644 index 000000000..d059d8476 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/ipsec.d/dnssec.keys @@ -0,0 +1,10 @@ +; This is a key-signing key, keyid 32329, for . +. IN DNSKEY 257 3 8 ( + AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2 + XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b + L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx + E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b + AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5 + nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO + O9fOgGnjzAk= + ) diff --git a/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/iptables.rules b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/iptables.rules new file mode 100644 index 000000000..b2c425289 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/iptables.rules @@ -0,0 +1,28 @@ +*filter + +# default policy is DROP +-P INPUT DROP +-P OUTPUT DROP +-P FORWARD DROP + +# allow esp +-A INPUT -i eth0 -p 50 -j ACCEPT +-A OUTPUT -o eth0 -p 50 -j ACCEPT + +# allow IKE +-A INPUT -i eth0 -p udp --sport 500 --dport 500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 500 --sport 500 -j ACCEPT + +# allow MobIKE +-A INPUT -i eth0 -p udp --sport 4500 --dport 4500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 4500 --sport 4500 -j ACCEPT + +# allow ssh +-A INPUT -p tcp --dport 22 -j ACCEPT +-A OUTPUT -p tcp --sport 22 -j ACCEPT + +# allow DNSSEC fetch from winnetou +-A INPUT -i eth0 -p udp --sport 53 -s PH_IP_WINNETOU -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 53 -d PH_IP_WINNETOU -j ACCEPT + +COMMIT diff --git a/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/resolv.conf b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/resolv.conf new file mode 100644 index 000000000..73d926def --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/resolv.conf @@ -0,0 +1 @@ +nameserver PH_IP_WINNETOU diff --git a/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/strongswan.conf b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/strongswan.conf new file mode 100644 index 000000000..825af9dd0 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/carol/etc/strongswan.conf @@ -0,0 +1,11 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce dnskey pubkey unbound ipseckey hmac stroke kernel-netlink socket-default updown resolve + + plugins { + ipseckey { + enable = yes + } + } +} diff --git a/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf new file mode 100644 index 000000000..24ffdd3b1 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.conf @@ -0,0 +1,23 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + keyexchange=ikev2 + +conn home + left=%any + leftsourceip=%config + leftid=dave.strongswan.org + leftrsasigkey="0sAwEAAcAH8lNvBVjmg0XT7wF6F1tzQ055f5uXRI5yClmFrqdswFA7jWO04jmvlduD2wr2X4Ng6dlBkSwSEhVkOgrzIYj8UgQT6BZF/44uYjyTYr4bV2SVML9U/a1lYxBhBazpSdfeKJWkdxwjcJCqolZ719mwiyrQn2P2G7qH10YgRuifpFcMs8jkMiIgpzevSMMc0OwhQPNyO5R0LEoUIy4dQJ9rU8GKqmPmk/pdPQaAjpSNuCc1Y9M9vZrETs/XHmBCZXCIWJiz5VOHZ+r073E3Gef9ibMuTj9g2XLvFhdDfU26FK9GkfuOwnWnhVK66diq9xw9Qqynk+8K0J4a81Paq3U=" + leftauth=pubkey + leftfirewall=yes + right=moon.strongswan.org + rightid=moon.strongswan.org + rightsubnet=10.1.0.0/16 + rightauth=pubkey + auto=add diff --git a/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.d/dnssec.keys b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.d/dnssec.keys new file mode 100644 index 000000000..d059d8476 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/ipsec.d/dnssec.keys @@ -0,0 +1,10 @@ +; This is a key-signing key, keyid 32329, for . +. IN DNSKEY 257 3 8 ( + AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2 + XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b + L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx + E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b + AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5 + nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO + O9fOgGnjzAk= + ) diff --git a/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/iptables.rules b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/iptables.rules new file mode 100644 index 000000000..b2c425289 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/iptables.rules @@ -0,0 +1,28 @@ +*filter + +# default policy is DROP +-P INPUT DROP +-P OUTPUT DROP +-P FORWARD DROP + +# allow esp +-A INPUT -i eth0 -p 50 -j ACCEPT +-A OUTPUT -o eth0 -p 50 -j ACCEPT + +# allow IKE +-A INPUT -i eth0 -p udp --sport 500 --dport 500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 500 --sport 500 -j ACCEPT + +# allow MobIKE +-A INPUT -i eth0 -p udp --sport 4500 --dport 4500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 4500 --sport 4500 -j ACCEPT + +# allow ssh +-A INPUT -p tcp --dport 22 -j ACCEPT +-A OUTPUT -p tcp --sport 22 -j ACCEPT + +# allow DNSSEC fetch from winnetou +-A INPUT -i eth0 -p udp --sport 53 -s PH_IP_WINNETOU -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 53 -d PH_IP_WINNETOU -j ACCEPT + +COMMIT diff --git a/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/resolv.conf b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/resolv.conf new file mode 100644 index 000000000..73d926def --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/resolv.conf @@ -0,0 +1 @@ +nameserver PH_IP_WINNETOU diff --git a/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/strongswan.conf b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/strongswan.conf new file mode 100644 index 000000000..825af9dd0 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/dave/etc/strongswan.conf @@ -0,0 +1,11 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce dnskey pubkey unbound ipseckey hmac stroke kernel-netlink socket-default updown resolve + + plugins { + ipseckey { + enable = yes + } + } +} diff --git a/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.conf b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.conf new file mode 100644 index 000000000..a199a4824 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.conf @@ -0,0 +1,22 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + keyexchange=ikev2 + +conn rw + left=PH_IP_MOON + leftsubnet=10.1.0.0/16 + leftid=moon.strongswan.org + leftauth=pubkey + leftrsasigkey=moonPub.der + leftfirewall=yes + right=%any + rightauth=pubkey + rightsourceip=10.3.0.0/24 + auto=add diff --git a/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.d/certs/moonPub.der b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.d/certs/moonPub.der Binary files differnew file mode 100644 index 000000000..71571044c --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.d/certs/moonPub.der diff --git a/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.d/dnssec.keys b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.d/dnssec.keys new file mode 100644 index 000000000..d059d8476 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/ipsec.d/dnssec.keys @@ -0,0 +1,10 @@ +; This is a key-signing key, keyid 32329, for . +. IN DNSKEY 257 3 8 ( + AwEAAbcskaratFgvgvXl0bNq4I43ZBzd9jYnoPqsIcA0ahqXlUTUa+c2 + XzN2mS7DGcI4Z5Gn+8v/Ih4lQJQrlf9I/c2HjooCAsK1bA5cRS2DiU+b + L6Ge0nLtvNOf4C0MHGLrWcDONg5QoL0OcFvMXuUtOvDkoIMdtfDYDScx + E9vSokc98Sx553/MTxpssXeM9i+OauGqohIZU+MVRdWwvJPieCL7Ma4b + AttgG+KSbQy7x/qXPISoqzwGQvCxsL93fvD/cpp+KziqA0oH+Dfryvc5 + nWdCdra4gYz7WCFFwcY1PW6PbL5ie4jnjl3WWxopuzT46HKROxDhE+FO + O9fOgGnjzAk= + ) diff --git a/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/iptables.rules b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/iptables.rules new file mode 100644 index 000000000..b2c425289 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/iptables.rules @@ -0,0 +1,28 @@ +*filter + +# default policy is DROP +-P INPUT DROP +-P OUTPUT DROP +-P FORWARD DROP + +# allow esp +-A INPUT -i eth0 -p 50 -j ACCEPT +-A OUTPUT -o eth0 -p 50 -j ACCEPT + +# allow IKE +-A INPUT -i eth0 -p udp --sport 500 --dport 500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 500 --sport 500 -j ACCEPT + +# allow MobIKE +-A INPUT -i eth0 -p udp --sport 4500 --dport 4500 -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 4500 --sport 4500 -j ACCEPT + +# allow ssh +-A INPUT -p tcp --dport 22 -j ACCEPT +-A OUTPUT -p tcp --sport 22 -j ACCEPT + +# allow DNSSEC fetch from winnetou +-A INPUT -i eth0 -p udp --sport 53 -s PH_IP_WINNETOU -j ACCEPT +-A OUTPUT -o eth0 -p udp --dport 53 -d PH_IP_WINNETOU -j ACCEPT + +COMMIT diff --git a/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/resolv.conf b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/resolv.conf new file mode 100644 index 000000000..73d926def --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/resolv.conf @@ -0,0 +1 @@ +nameserver PH_IP_WINNETOU diff --git a/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/strongswan.conf b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/strongswan.conf new file mode 100644 index 000000000..644ac3d6a --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/hosts/moon/etc/strongswan.conf @@ -0,0 +1,14 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = aes des sha1 sha2 md5 pem pkcs1 dnskey pubkey unbound ipseckey gmp random nonce hmac stroke kernel-netlink socket-default updown attr + + dns1 = PH_IP_WINNETOU + dns2 = PH_IP_VENUS + + plugins { + ipseckey { + enable = yes + } + } +} diff --git a/testing/tests/ikev2/rw-dnssec/posttest.dat b/testing/tests/ikev2/rw-dnssec/posttest.dat new file mode 100644 index 000000000..3d55e09f9 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/posttest.dat @@ -0,0 +1,12 @@ +moon::ipsec stop +carol::ipsec stop +dave::ipsec stop +moon::iptables-restore < /etc/iptables.flush +carol::iptables-restore < /etc/iptables.flush +dave::iptables-restore < /etc/iptables.flush +moon:rm /etc/resolv.conf +carol:rm /etc/resolv.conf +dave:rm /etc/resolv.conf +moon:rm /etc/ipsec.d/dnssec.key +carol:rm /etc/ipsec.d/dnssec.key +dave:rm /etc/ipse.cd/dnssec.key diff --git a/testing/tests/ikev2/rw-dnssec/pretest.dat b/testing/tests/ikev2/rw-dnssec/pretest.dat new file mode 100644 index 000000000..40eaede87 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/pretest.dat @@ -0,0 +1,13 @@ +moon::iptables-restore < /etc/iptables.rules +carol::iptables-restore < /etc/iptables.rules +dave::iptables-restore < /etc/iptables.rules +moon::rm /etc/ipsec.d/cacerts/* +carol::rm /etc/ipsec.d/cacerts/* +dave::rm /etc/ipsec.d/cacerts/* +carol::ipsec start +dave::ipsec start +moon::ipsec start +carol::sleep 2 +carol::ipsec up home +dave::ipsec up home +carol::sleep 1 diff --git a/testing/tests/ikev2/rw-dnssec/test.conf b/testing/tests/ikev2/rw-dnssec/test.conf new file mode 100644 index 000000000..164b07ff9 --- /dev/null +++ b/testing/tests/ikev2/rw-dnssec/test.conf @@ -0,0 +1,21 @@ +#!/bin/bash +# +# This configuration file provides information on the +# guest instances used for this test + +# All guest instances that are required for this test +# +VIRTHOSTS="alice moon carol winnetou dave" + +# Corresponding block diagram +# +DIAGRAM="a-m-c-w-d.png" + +# Guest instances on which tcpdump is to be started +# +TCPDUMPHOSTS="moon alice" + +# Guest instances on which IPsec is started +# Used for IPsec logging purposes +# +IPSECHOSTS="moon carol dave" diff --git a/testing/tests/openssl-ikev2/alg-aes-gcm/description.txt b/testing/tests/openssl-ikev2/alg-aes-gcm/description.txt new file mode 100644 index 000000000..cfa7a11b9 --- /dev/null +++ b/testing/tests/openssl-ikev2/alg-aes-gcm/description.txt @@ -0,0 +1,16 @@ +The roadwarrior <b>carol</b> and the gateway <b>moon</b> use the <b>openssl</b> +plugin based on the <b>OpenSSL</b> library for all cryptographical and X.509 certificate +functions whereas roadwarrior <b>dave</b> uses the default <b>strongSwan</b> cryptographical +plugins <b>aes des sha1 sha2 md5 gmp hmac gcm</b> and <b>x509</b>. +<p/> +Roadwarrior <b>carol</b> proposes to gateway <b>moon</b> the cipher suite +<b>AES_GCM_16_256</b> both for IKE and ESP by defining <b>ike=aes256gcm16-prfsha512-modp2048</b> +(or alternatively <b>aes256gcm128</b>) and <b>esp=aes256gcm16-modp2048</b> in ipsec.conf, +respectively. +<p/> +Roadwarrior <b>dave</b> proposes to gateway <b>moon</b> the cipher suite +<b>AES_GCM_16_128</b> both for IKE and ESP by defining <b>ike=aes128gcm16-prfsha256-modp1536</b> +(or alternatively <b>aes128gcm128</b>) and <b>esp=aes128gcm16-modp1536</b> in ipsec.conf, +respectively. +<p/> +A ping by <b>carol</b> and <b>dave</b> to <b>alice</b> successfully checks the established tunnels. diff --git a/testing/tests/openssl-ikev2/alg-aes-gcm/evaltest.dat b/testing/tests/openssl-ikev2/alg-aes-gcm/evaltest.dat new file mode 100644 index 000000000..4cf89b765 --- /dev/null +++ b/testing/tests/openssl-ikev2/alg-aes-gcm/evaltest.dat @@ -0,0 +1,26 @@ +moon:: ipsec status 2> /dev/null::rw\[1]: ESTABLISHED.*moon.strongswan.org.*carol@strongswan.org::YES +moon:: ipsec status 2> /dev/null::rw\[2]: ESTABLISHED.*moon.strongswan.org.*dave@strongswan.org::YES +carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol@strongswan.org.*moon.strongswan.org::YES +dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave@strongswan.org.*moon.strongswan.org::YES +moon:: ipsec status 2> /dev/null::rw[{]1}.*INSTALLED, TUNNEL::YES +moon:: ipsec status 2> /dev/null::rw[{]2}.*INSTALLED, TUNNEL::YES +carol::ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES +dave:: ipsec status 2> /dev/null::home.*INSTALLED, TUNNEL::YES +carol::ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES +dave:: ping -c 1 -s 120 -p deadbeef PH_IP_ALICE::128 bytes from PH_IP_ALICE: icmp_req=1::YES +moon:: ipsec statusall 2> /dev/null::rw\[1].*IKE proposal: AES_GCM_16_256::YES +moon:: ipsec statusall 2> /dev/null::rw\[2].*IKE proposal: AES_GCM_16_128::YES +carol::ipsec statusall 2> /dev/null::IKE proposal: AES_GCM_16_256::YES +dave:: ipsec statusall 2> /dev/null::IKE proposal: AES_GCM_16_128::YES +moon:: ipsec statusall 2> /dev/null::rw[{]1}.*AES_GCM_16_256,::YES +moon:: ipsec statusall 2> /dev/null::rw[{]2}.*AES_GCM_16_128,::YES +carol::ipsec statusall 2> /dev/null::AES_GCM_16_256,::YES +dave:: ipsec statusall 2> /dev/null::AES_GCM_16_128,::YES +moon:: ip xfrm state::aead rfc4106(gcm(aes))::YES +carol::ip xfrm state::aead rfc4106(gcm(aes))::YES +dave:: ip xfrm state::aead rfc4106(gcm(aes))::YES +moon::tcpdump::IP carol.strongswan.org > moon.strongswan.org: ESP.*length 184::YES +moon::tcpdump::IP moon.strongswan.org > carol.strongswan.org: ESP.*length 184::YES +moon::tcpdump::IP dave.strongswan.org > moon.strongswan.org: ESP.*length 184::YES +moon::tcpdump::IP moon.strongswan.org > dave.strongswan.org: ESP.*length 184::YES + diff --git a/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/carol/etc/ipsec.conf b/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/carol/etc/ipsec.conf new file mode 100644 index 000000000..c0016ff61 --- /dev/null +++ b/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/carol/etc/ipsec.conf @@ -0,0 +1,22 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + keyexchange=ikev2 + ike=aes256gcm128-prfsha512-modp2048! + esp=aes256gcm128-modp2048! + +conn home + left=PH_IP_CAROL + leftfirewall=yes + leftcert=carolCert.pem + leftid=carol@strongswan.org + right=PH_IP_MOON + rightsubnet=10.1.0.0/16 + rightid=@moon.strongswan.org + auto=add diff --git a/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/carol/etc/strongswan.conf b/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/carol/etc/strongswan.conf new file mode 100644 index 000000000..5481f7b72 --- /dev/null +++ b/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/carol/etc/strongswan.conf @@ -0,0 +1,5 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl pem pkcs1 random nonce revocation openssl stroke kernel-netlink socket-default updown +} diff --git a/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/dave/etc/ipsec.conf b/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/dave/etc/ipsec.conf new file mode 100644 index 000000000..335eda02c --- /dev/null +++ b/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/dave/etc/ipsec.conf @@ -0,0 +1,22 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + keyexchange=ikev2 + ike=aes128gcm128-prfsha256-modp1536! + esp=aes128gcm128-modp1536! + +conn home + left=PH_IP_DAVE + leftfirewall=yes + leftcert=daveCert.pem + leftid=dave@strongswan.org + right=PH_IP_MOON + rightsubnet=10.1.0.0/16 + rightid=@moon.strongswan.org + auto=add diff --git a/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/dave/etc/strongswan.conf b/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/dave/etc/strongswan.conf new file mode 100644 index 000000000..564e4ea8c --- /dev/null +++ b/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/dave/etc/strongswan.conf @@ -0,0 +1,5 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac gcm stroke kernel-netlink socket-default updown +} diff --git a/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/moon/etc/ipsec.conf b/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/moon/etc/ipsec.conf new file mode 100644 index 000000000..566298bed --- /dev/null +++ b/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/moon/etc/ipsec.conf @@ -0,0 +1,21 @@ +# /etc/ipsec.conf - strongSwan IPsec configuration file + +config setup + +conn %default + ikelifetime=60m + keylife=20m + rekeymargin=3m + keyingtries=1 + keyexchange=ikev2 + ike=aes256gcm16-prfsha512-modp2048,aes128gcm16-prfsha256-modp1536! + esp=aes256gcm16-modp2048,aes128gcm16-modp1536! + +conn rw + left=PH_IP_MOON + leftfirewall=yes + leftcert=moonCert.pem + leftid=@moon.strongswan.org + leftsubnet=10.1.0.0/16 + right=%any + auto=add diff --git a/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/moon/etc/strongswan.conf b/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/moon/etc/strongswan.conf new file mode 100644 index 000000000..5481f7b72 --- /dev/null +++ b/testing/tests/openssl-ikev2/alg-aes-gcm/hosts/moon/etc/strongswan.conf @@ -0,0 +1,5 @@ +# /etc/strongswan.conf - strongSwan configuration file + +charon { + load = curl pem pkcs1 random nonce revocation openssl stroke kernel-netlink socket-default updown +} diff --git a/testing/tests/openssl-ikev2/alg-aes-gcm/posttest.dat b/testing/tests/openssl-ikev2/alg-aes-gcm/posttest.dat new file mode 100644 index 000000000..1865a1c60 --- /dev/null +++ b/testing/tests/openssl-ikev2/alg-aes-gcm/posttest.dat @@ -0,0 +1,6 @@ +moon::ipsec stop +carol::ipsec stop +dave::ipsec stop +moon::iptables-restore < /etc/iptables.flush +carol::iptables-restore < /etc/iptables.flush +dave::iptables-restore < /etc/iptables.flush diff --git a/testing/tests/openssl-ikev2/alg-aes-gcm/pretest.dat b/testing/tests/openssl-ikev2/alg-aes-gcm/pretest.dat new file mode 100644 index 000000000..972d93053 --- /dev/null +++ b/testing/tests/openssl-ikev2/alg-aes-gcm/pretest.dat @@ -0,0 +1,9 @@ +moon::iptables-restore < /etc/iptables.rules +carol::iptables-restore < /etc/iptables.rules +dave::iptables-restore < /etc/iptables.rules +moon::ipsec start +carol::ipsec start +dave::ipsec start +carol::sleep 1 +carol::ipsec up home +dave::ipsec up home diff --git a/testing/tests/openssl-ikev2/alg-aes-gcm/test.conf b/testing/tests/openssl-ikev2/alg-aes-gcm/test.conf new file mode 100644 index 000000000..c3f38054b --- /dev/null +++ b/testing/tests/openssl-ikev2/alg-aes-gcm/test.conf @@ -0,0 +1,21 @@ +#!/bin/bash +# +# This configuration file provides information on the +# guest instances used for this test + +# All guest instances that are required for this test +# +VIRTHOSTS="alice moon carol dave winnetou" + +# Corresponding block diagram +# +DIAGRAM="a-m-c-w-d.png" + +# Guest instances on which tcpdump is to be started +# +TCPDUMPHOSTS="moon" + +# Guest instances on which IPsec is started +# Used for IPsec logging purposes +# +IPSECHOSTS="moon carol dave" diff --git a/testing/tests/tnc/tnccs-20-pdp/evaltest.dat b/testing/tests/tnc/tnccs-20-pdp/evaltest.dat index e969774c5..f028ec609 100644 --- a/testing/tests/tnc/tnccs-20-pdp/evaltest.dat +++ b/testing/tests/tnc/tnccs-20-pdp/evaltest.dat @@ -7,9 +7,11 @@ dave:: cat /var/log/daemon.log::PB-TNC access recommendation is .*Quarantined::Y dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established::YES dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES moon:: cat /var/log/daemon.log::received RADIUS attribute Filter-Id: 'allow'::YES -moon:: cat /var/log/daemon.log::authentication of 'carol@strongswan.org' with EAP successful::YES +moon:: cat /var/log/daemon.log::RADIUS authentication of 'carol' successful::YES +moon:: cat /var/log/daemon.log::authentication of '192.168.0.100' with EAP successful::YES moon:: cat /var/log/daemon.log::received RADIUS attribute Filter-Id: 'isolate'::YES -moon:: cat /var/log/daemon.log::authentication of 'dave@strongswan.org' with EAP successful::YES +moon:: cat /var/log/daemon.log::RADIUS authentication of 'dave' successful::YES +moon:: cat /var/log/daemon.log::authentication of '192.168.0.200' with EAP successful::YES moon:: ipsec statusall 2>/dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES moon:: ipsec statusall 2>/dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.secrets index 96b9a8dd5..11d45cd14 100644 --- a/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.secrets +++ b/testing/tests/tnc/tnccs-20-pdp/hosts/alice/etc/ipsec.secrets @@ -2,5 +2,5 @@ : RSA aaaKey.pem -carol@strongswan.org : EAP "Ar3etTnp" -dave@strongswan.org : EAP "W7R0g3do" +carol : EAP "Ar3etTnp" +dave : EAP "W7R0g3do" diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/ipsec.conf index e9152e0d8..59563730b 100644 --- a/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/ipsec.conf +++ b/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/ipsec.conf @@ -12,12 +12,12 @@ conn %default conn home left=PH_IP_CAROL - leftid=carol@strongswan.org leftauth=eap leftfirewall=yes right=PH_IP_MOON rightid=@moon.strongswan.org rightsubnet=10.1.0.0/16 rightauth=pubkey + eap_identity=carol aaa_identity="C=CH, O=Linux strongSwan, CN=aaa.strongswan.org" auto=add diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/ipsec.secrets index 74942afda..23d79cf2e 100644 --- a/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/ipsec.secrets +++ b/testing/tests/tnc/tnccs-20-pdp/hosts/carol/etc/ipsec.secrets @@ -1,3 +1,3 @@ # /etc/ipsec.secrets - strongSwan IPsec secrets file -carol@strongswan.org : EAP "Ar3etTnp" +carol : EAP "Ar3etTnp" diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/ipsec.conf index 25589bcf1..8c27c78d2 100644 --- a/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/ipsec.conf +++ b/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/ipsec.conf @@ -12,12 +12,12 @@ conn %default conn home left=PH_IP_DAVE - leftid=dave@strongswan.org leftauth=eap leftfirewall=yes right=PH_IP_MOON rightid=@moon.strongswan.org rightsubnet=10.1.0.0/16 rightauth=pubkey + eap_identity=dave aaa_identity="C=CH, O=Linux strongSwan, CN=aaa.strongswan.org" auto=add diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/ipsec.secrets index 5496df7ad..02e0c9963 100644 --- a/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/ipsec.secrets +++ b/testing/tests/tnc/tnccs-20-pdp/hosts/dave/etc/ipsec.secrets @@ -1,3 +1,3 @@ # /etc/ipsec.secrets - strongSwan IPsec secrets file -dave@strongswan.org : EAP "W7R0g3do" +dave : EAP "W7R0g3do" diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/ipsec.conf index 294964fe7..02ada5665 100644 --- a/testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/ipsec.conf +++ b/testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/ipsec.conf @@ -28,6 +28,6 @@ conn rw-eap leftauth=pubkey leftfirewall=yes rightauth=eap-radius - rightid=*@strongswan.org rightsendcert=never right=%any + eap_identity=%any diff --git a/testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/strongswan.conf index 15655daf2..d32951866 100644 --- a/testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/strongswan.conf +++ b/testing/tests/tnc/tnccs-20-pdp/hosts/moon/etc/strongswan.conf @@ -1,7 +1,7 @@ # /etc/strongswan.conf - strongSwan configuration file charon { - load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-radius updown + load = curl aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 revocation hmac stroke kernel-netlink socket-default eap-identity eap-radius updown multiple_authentication=no plugins { eap-radius { diff --git a/testing/tests/tnc/tnccs-20-tls/evaltest.dat b/testing/tests/tnc/tnccs-20-tls/evaltest.dat index bac7294b2..40d5e24d5 100644 --- a/testing/tests/tnc/tnccs-20-tls/evaltest.dat +++ b/testing/tests/tnc/tnccs-20-tls/evaltest.dat @@ -7,9 +7,9 @@ dave:: cat /var/log/daemon.log::EAP method EAP_TTLS succeeded, MSK established:: dave:: cat /var/log/daemon.log::authentication of 'moon.strongswan.org' with EAP successful::YES dave:: cat /var/log/daemon.log::CHILD_SA home{1} established.*TS 192.168.0.200/32 === 10.1.0.16/28::YES moon:: cat /var/log/daemon.log::added group membership 'allow'::YES -moon:: cat /var/log/daemon.log::authentication of 'carol@strongswan.org' with EAP successful::YES +moon:: cat /var/log/daemon.log::authentication of 'C=CH, O=Linux strongSwan, OU=Research, CN=carol@strongswan.org' with EAP successful::YES moon:: cat /var/log/daemon.log::added group membership 'isolate'::YES -moon:: cat /var/log/daemon.log::authentication of 'dave@strongswan.org' with EAP successful::YES +moon:: cat /var/log/daemon.log::authentication of 'C=CH, O=Linux strongSwan, OU=Accounting, CN=dave@strongswan.org' with EAP successful::YES moon:: ipsec statusall 2> /dev/null::rw-allow.*10.1.0.0/28 === 192.168.0.100/32::YES moon:: ipsec statusall 2> /dev/null::rw-isolate.*10.1.0.16/28 === 192.168.0.200/32::YES carol::ping -c 1 PH_IP_ALICE::64 bytes from PH_IP_ALICE: icmp_req=1::YES diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/ipsec.conf index e9b78bc01..eece9f294 100644 --- a/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/ipsec.conf +++ b/testing/tests/tnc/tnccs-20-tls/hosts/carol/etc/ipsec.conf @@ -13,7 +13,6 @@ conn %default conn home left=PH_IP_CAROL leftcert=carolCert.pem - leftid=carol@strongswan.org leftauth=eap leftfirewall=yes right=PH_IP_MOON diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/ipsec.conf index 75d84e25a..362042656 100644 --- a/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/ipsec.conf +++ b/testing/tests/tnc/tnccs-20-tls/hosts/dave/etc/ipsec.conf @@ -13,7 +13,6 @@ conn %default conn home left=PH_IP_DAVE leftcert=daveCert.pem - leftid=dave@strongswan.org leftauth=eap leftfirewall=yes right=PH_IP_MOON diff --git a/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/ipsec.conf index 2ffc7e9ae..0ec930286 100644 --- a/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/ipsec.conf +++ b/testing/tests/tnc/tnccs-20-tls/hosts/moon/etc/ipsec.conf @@ -29,6 +29,6 @@ conn rw-eap leftauth=eap-ttls leftfirewall=yes rightauth=eap-ttls - rightid=*@strongswan.org + rightid="C=CH, O=Linux strongSwan, OU=*, CN=*" rightsendcert=never right=%any |