This commit is contained in:
christos 2020-03-03 00:18:44 +00:00
parent 95f430ca15
commit 46988a0ecd
48 changed files with 5339 additions and 0 deletions

106
external/bsd/pam-u2f/dist/.clang-format vendored Normal file
View File

@ -0,0 +1,106 @@
---
Language: Cpp
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: true
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1000
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: true
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
...

253
external/bsd/pam-u2f/dist/.travis.yml vendored Normal file
View File

@ -0,0 +1,253 @@
language: c
matrix:
include:
- name: Xenial gcc-7
os: linux
compiler: gcc-7
dist: xenial
addons:
apt:
sources:
- sourceline: 'ppa:yubico/stable'
- ubuntu-toolchain-r-test
packages:
- autoconf
- check
- gcc-7
- gengetopt
- help2man
- libfido2-dev
- libpam-dev
- libssl-dev
- libtool
- pkg-config
script: ./build-aux/ci/build-xenial-gcc7.sh
- name: Xenial gcc-8
os: linux
compiler: gcc-8
dist: xenial
addons:
apt:
sources:
- sourceline: 'ppa:yubico/stable'
- ubuntu-toolchain-r-test
packages:
- autoconf
- check
- gcc-8
- gengetopt
- help2man
- libfido2-dev
- libpam-dev
- libssl-dev
- libtool
- pkg-config
script: ./build-aux/ci/build-xenial-gcc8.sh
- name: Xenial gcc-9
os: linux
compiler: gcc-9
dist: xenial
addons:
apt:
sources:
- sourceline: 'ppa:yubico/stable'
- ubuntu-toolchain-r-test
packages:
- autoconf
- check
- gcc-9
- gengetopt
- help2man
- libfido2-dev
- libpam-dev
- libssl-dev
- libtool
- pkg-config
script: ./build-aux/ci/build-xenial-gcc9.sh
- name: Xenial clang-7
os: linux
compiler: clang-7
dist: xenial
addons:
apt:
sources:
- sourceline: 'ppa:yubico/stable'
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-7
packages:
- autoconf
- check
- clang-7
- gengetopt
- help2man
- libfido2-dev
- libpam-dev
- libssl-dev
- libtool
- pkg-config
script: ./build-aux/ci/build-xenial-clang7.sh
- name: Xenial clang-8
os: linux
compiler: clang-8
dist: xenial
addons:
apt:
sources:
- sourceline: 'ppa:yubico/stable'
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
packages:
- autoconf
- check
- clang-8
- gengetopt
- help2man
- libfido2-dev
- libpam-dev
- libssl-dev
- libtool
- pkg-config
script: ./build-aux/ci/build-xenial-clang8.sh
- name: Bionic gcc-7 and clang-format
os: linux
compiler: gcc-7
dist: bionic
addons:
apt:
sources:
- sourceline: 'ppa:yubico/stable'
- ubuntu-toolchain-r-test
packages:
- autoconf
- check
- clang-format-6.0
- gcc-7
- gengetopt
- help2man
- libfido2-dev
- libpam-dev
- libssl-dev
- libtool
- pkg-config
script: ./build-aux/ci/build-bionic-gcc7.sh
- name: Bionic gcc-8
os: linux
compiler: gcc-8
dist: bionic
addons:
apt:
sources:
- sourceline: 'ppa:yubico/stable'
- ubuntu-toolchain-r-test
packages:
- autoconf
- check
- gcc-8
- gengetopt
- help2man
- libfido2-dev
- libpam-dev
- libssl-dev
- libtool
- pkg-config
script: ./build-aux/ci/build-bionic-gcc8.sh
- name: Bionic gcc-9
os: linux
compiler: gcc-9
dist: bionic
addons:
apt:
sources:
- sourceline: 'ppa:yubico/stable'
- sourceline: 'ppa:ubuntu-toolchain-r/test'
packages:
- autoconf
- check
- gcc-9
- gengetopt
- help2man
- libfido2-dev
- libpam-dev
- libssl-dev
- libtool
- pkg-config
script: ./build-aux/ci/build-bionic-gcc9.sh
- name: Bionic clang-7
os: linux
compiler: clang-7
dist: bionic
addons:
apt:
sources:
- sourceline: 'ppa:yubico/stable'
- sourceline: 'ppa:ubuntu-toolchain-r/test'
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-7 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
packages:
- autoconf
- check
- clang-7
- gengetopt
- help2man
- libfido2-dev
- libpam-dev
- libssl-dev
- libtool
- pkg-config
script: ./build-aux/ci/build-bionic-clang7.sh
- name: Bionic clang-8
os: linux
compiler: clang-8
dist: bionic
addons:
apt:
sources:
- sourceline: 'ppa:yubico/stable'
- sourceline: 'ppa:ubuntu-toolchain-r/test'
- sourceline: 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-8 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
packages:
- autoconf
- check
- clang-8
- gengetopt
- help2man
- libfido2-dev
- libpam-dev
- libssl-dev
- libtool
- pkg-config
script: ./build-aux/ci/build-bionic-clang8.sh
- name: macOS xcode9.4
os: osx
osx_image: xcode9.4
compiler: clang
addons:
homebrew:
packages:
- check
- cmake
- gengetopt
- help2man
- mandoc
- openssl@1.1
- pkg-config
update: true
script: ./build-aux/ci/build-osx9.4-clang.sh
- name: macOS xcode11
os: osx
osx_image: xcode11
compiler: clang
addons:
homebrew:
packages:
- check
- cmake
- gengetopt
- help2man
- mandoc
- openssl@1.1
- pkg-config
update: true
script: ./build-aux/ci/build-osx11-clang.sh

1
external/bsd/pam-u2f/dist/AUTHORS vendored Normal file
View File

@ -0,0 +1 @@
Alessio Di Mauro <alessio@yubico.com>

26
external/bsd/pam-u2f/dist/COPYING vendored Normal file
View File

@ -0,0 +1,26 @@
Copyright (c) 2014-2018 Yubico AB
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

76
external/bsd/pam-u2f/dist/Makefile.am vendored Normal file
View File

@ -0,0 +1,76 @@
# Copyright (C) 2014-2018 Yubico AB - See COPYING
SUBDIRS = . pamu2fcfg tests
ACLOCAL_AMFLAGS = -I m4
AM_CFLAGS = $(CWFLAGS)
AM_CPPFLAGS = $(LIBFIDO2_CFLAGS) $(LIBCRYPTO_CFLAGS)
libdir = $(PAMDIR)
lib_LTLIBRARIES = pam_u2f.la
pam_u2f_la_SOURCES = pam-u2f.c
pam_u2f_la_SOURCES += util.c util.h
pam_u2f_la_SOURCES += drop_privs.h drop_privs.c
pam_u2f_la_SOURCES += b64.c b64.h
pam_u2f_la_SOURCES += explicit_bzero.c
pam_u2f_la_LIBADD = -lpam
pam_u2f_la_LIBADD += $(LIBFIDO2_LIBS) $(LIBCRYPTO_LIBS)
pam_u2f_la_LDFLAGS = -module -avoid-version
DEFS = -DDEBUG_PAM -DPAM_DEBUG @DEFS@
if ENABLE_MAN
dist_man8_MANS = $(top_builddir)/man/pam_u2f.8
DISTCLEANFILES = $(dist_man8_MANS)
MANSOURCES = $(top_builddir)/man/pam_u2f.8.txt
EXTRA_DIST = $(MANSOURCES)
SUFFIXES = .8.txt .8
.8.txt.8:
$(A2X) --format=manpage -L -a revdate="Version $(VERSION)" $<
endif
# Release
install-exec-hook:
rm -f $(PAMDIR)/pam_u2f.la
chmod -f 644 $(PAMDIR)/pam_u2f.so || true
indent:
clang-format -i *.c *.h pamu2fcfg/*.c pamu2fcfg/*.h
ChangeLog:
cd $(srcdir) && git2cl > ChangeLog
PROJECT = pam-u2f
release:
@if test ! -d "$(YUBICO_WWW_REPO)"; then \
echo "WWW repo not found!"; \
echo "Make sure that YUBICO_WWW_REPO is set"; \
exit 1; \
fi
@if test -z "$(KEYID)"; then \
echo "Try this instead:"; \
echo " make release KEYID=[PGPKEYID]"; \
echo "For example:"; \
echo " make release KEYID=2117364A"; \
exit 1; \
fi
@head -5 $(srcdir)/NEWS | \
grep -q "Version $(VERSION) .released `date -I`" || \
(echo 'error: Update date/version in $(srcdir)/NEWS.'; exit 1)
rm -f $(srcdir)/ChangeLog
sudo make ChangeLog distcheck
gpg --detach-sign --default-key $(KEYID) $(PACKAGE)-$(VERSION).tar.gz
gpg --verify $(PACKAGE)-$(VERSION).tar.gz.sig
cd $(srcdir) && git push
cd $(srcdir) && git tag -u $(KEYID) -m $(VERSION) $(PACKAGE)-$(VERSION)
cd $(srcdir) && git push --tags
$(YUBICO_WWW_REPO)/publish $(PROJECT) $(VERSION) $(PACKAGE)-$(VERSION).tar.gz*

48
external/bsd/pam-u2f/dist/NEWS vendored Normal file
View File

@ -0,0 +1,48 @@
Copyright (c) 2014-2018 Yubico AB - See COPYING
pam-u2f NEWS -- History of user-visible changes. -*- outline -*-
* Version 1.0.9 (unreleased)
* Version 1.0.8 (released 2019-06-04)
** Fix debug file descriptor leak CVE-2019-12210.
** Fix insecure debug file handling CVE-2019-12209.
Both reported by Matthias Gerstner of the SUSE Security Team.
** Fix a non-critical buffer oob access.
* Version 1.0.7 (released 2018-05-15)
** Add authpending_file to signal authentication activity
** Add nodetect to skip to avoid unnecessary cue messages
* Version 1.0.6 (released 2018-04-18)
** Fix an issue when using syslog as a debug facility.
** Do not honor cue if no sutable device is found.
* Version 1.0.5 (released 2018-04-16)
** General bugfixes and quality-of-life improvements.
* Version 1.0.4 (released 2016-01-07)
** Fixed possible permission escalation when using XDG_CONFIG_HOME.
* Version 1.0.3 (released 2015-11-02)
** Bugfix in pamu2fcfg.
** Minor improvements for verbose mode in pamu2fcfg.
* Version 1.0.2 (released 2015-10-06)
** Changes to automake flags.
** Improve build on OS X.
* Version 1.0.1 (released 2015-06-18)
** Minor changes to man pages and install hooks.
* Version 1.0.0 (released 2015-06-17)
** Use XDG_CONFIG_HOME as default for config files.
** Added manual and interactive mode.
** Added verbose mode.
* Version 0.0.1 (released 2015-01-16)
** Changed failure mode after authentication error.
** Added call to setcred.
* Version 0.0.0 (released 2014-12-16)
** Initial release.

272
external/bsd/pam-u2f/dist/README vendored Normal file
View File

@ -0,0 +1,272 @@
Pluggable Authentication Module (PAM) Universal 2nd Factor (U2F)
================================================================
image:https://travis-ci.org/Yubico/pam-u2f.svg?branch=master["Build Status", link="https://travis-ci.org/Yubico/pam-u2f"]
image:https://scan.coverity.com/projects/5711/badge.svg["Coverity Status", link=https://scan.coverity.com/projects/5711]
This module implements PAM over U2F, providing an easy way to integrate the
YubiKey (or other U2F compliant authenticators) into your existing
infrastructure.
[[building]]
Building
--------
This project uses 'autoconf', 'automake', 'pkg-config' and 'libtool'
to achieve portability and ease of use.
In addition, both the Yubico U2F https://developers.yubico.com/libu2f-host['libu2f-host-dev'] and
https://developers.yubico.com/libu2f-server['libu2f-server-dev'] libaries are needed.
Debian: apt-get install autoconf automake libtool pkg-config libu2f-host-dev libu2f-server-dev --no-install-recommends
If you downloaded a tarball, build it as follows.
-----------
$ ./configure
$ make
-----------
Building from Git
-----------------
You may check out the sources using Git with the following command:
-----------
$ git clone git://github.com/Yubico/pam-u2f.git
-----------
This will create a directory 'pam-u2f'. Enter the directory:
-----------
$ cd pam-u2f
-----------
'Autoconf', 'automake', 'libtool', and 'libpam' must be installed. 'AsciiDoc' and 'xsltproc' are used to
generate the manpages.
Debian: apt-get install autoconf automake libtool libpam-dev libu2f-host-dev libu2f-server-dev asciidoc xsltproc libxml2-utils docbook-xml --no-install-recommends
Generate the build system using:
-----------
$ autoreconf --install
-----------
Then build as usual, see above under <<building,Building>>.
Installation
------------
Once the module is built copy the file +pam_u2f.so+ to the correct
directory for your system. Typically +/lib/security/+ or
+/lib/x86_64-linux-gnu/security/+. This is automated by +make install+
assuming that the pam directory chosen by +configure+ is correct.
If that is not the case it can be specified with +./configure --with-pam-dir=+.
Create a file for a new service in +/etc/pam.d/+ or edit an already
existing one by adding a line similar to this:
----
auth sufficient pam_u2f.so debug
----
Supported parameters for the module are:
[horizontal]
debug::
Enables debug output
debug_file::
Filename to write debugging messages to. **If this file is missing, nothing will be logged**. This regular file **has to be created by the user**
or **must exist and be a regular file** for anything getting logged to it. It is not created by pam-u2f on purpose (for security considerations).
This filename may be alternatively set to "stderr" (default), "stdout", or "syslog".
origin=origin::
Set the origin for the U2F authentication procedure.
If no value is specified, the origin "pam://$HOSTNAME" is used.
appid=appid::
Set the https://developers.yubico.com/U2F/App_ID.html[application ID] for the U2F authentication procedure.
If no value is specified, the same value used for origin is taken
("pam://$HOSTNAME" if also origin is not specified).
authfile=file::
Set the location of the file that holds the mappings of user names
to keyHandles and user keys. The format is
+username:first_keyHandle,first_public_key:
second_keyHandle,second_public_key:...+ the default location of the
file is $XDG_CONFIG_HOME/Yubico/u2f_keys. If the environment variable
is not set, $HOME/.config/Yubico/u2f_keys is used.
(more on <<files,Authorization Mapping Files>>). An individual (per user) file
may be configured, see <<individualAuth>>.
authpending_file=file::
Set the location of the file that is used for touch request notifications.
This file will be opened when pam-u2f starts waiting for a user to touch the device,
and will be closed when it no longer waits for a touch.
Use inotify to listen on these events, or a more high-level tool like https://github.com/maximbaz/yubikey-touch-detector[yubikey-touch-detector].
Set an empty value in order to disable this functionality, like so: `authpending_file=`.
Default value: /var/run/user/$UID/pam-u2f-authpending
nouserok::
Set to enable authentication attempts to succeed even if the user trying to
authenticate is not found inside authfile or if authfile is missing/malformed.
openasuser::
Setuid to the authenticating user when opening the authfile. Useful when the
user's home is stored on an NFS volume mounted with the root_squash option
(which maps root to nobody which will not be able to read the file).
Note that after release 1.0.8 this is done by default when no global
authfile or XDG_CONFIG_HOME environment variable has been set.
alwaysok::
Set to enable all authentication attempts to succeed (aka presentation mode).
max_devices=n_devices::
Maximum number of devices allowed per user (default is 24). Devices specified
in the authentication file that exceed this value will be ignored.
interactive::
Set to prompt a message and wait before testing the presence of a U2F device.
Recommended if your device doesn't have a tactile trigger.
[prompt=your prompt here]::
Set individual prompt message for interactive mode. Watch the square brackets
around this parameter to get spaces correctly recognized by PAM.
manual::
Set to drop to a manual console where challenges are printed on screen
and response read from standard input. Useful for debugging and SSH sessions
without U2F-support from the SSH client/server.
If enabled, interactive mode becomes redundant and has no effect.
cue::
Set to prompt a message to remind to touch the device.
[cue_prompt=your prompt here]::
Set individual prompt message for the cue option. Watch the square brackets
around this parameter to get spaces correctly recognized by PAM.
nodetect::
Set to skip detecting if a suitable U2F token is inserted before performing
the full tactile authentication. This detection was created to avoid
emitting the "cue" message if no suitable token exists, because doing so
leaks information about the authentication stack if a token is inserted but
not configured for the authenticating user. However, it was found that
versions of libu2f-user 1.1.5 or less has buggy iteration/sleep behavior
which causes a 1-second delay to occur for this initial detection. For this
reason, as well as the possibility of hypothetical tokens that do not
tolerate this double authentication, the "nodetect" option was added.
userpresence=int::
If 1, request user presence during authentication. If 0, do not request user
presence during authentication. Otherwise, fallback to the authenticator's
default behaviour.
userverification=int::
If 1, request user verification during authentication. If 0, do not request
user verification during authentication. Otherwise, fallback to the
authenticator's default behaviour.
pinverification=int::
If 1, request PIN verification during authentication. If 0, do not request
PIN verification during authentication. Otherwise, fallback to the
authenticator's default behaviour.
[[files]]
Authorization Mapping Files
---------------------------
A mapping must be made between the YubiKey token and the user name,
see <<registration, here>> for details on how to perform the registration
using the bundled tool.
There are two ways to do this, either centrally in one file, or
individually, where users can create the mapping in their home directories.
If the central authorization mapping file is being used, user home directory
mappings will not be used and the opposite applies if user home directory
mappings are being used, the central authorization mappings file will not
be used.
By default the mapping file inside a home directory will be opened as
the target user, whereas the central file will be opened as `root`. If
the `XDG_CONFIG_HOME` variable is set, privileges will not be dropped
unless the `openasuser` configuration setting is set.
IMPORTANT: Using pam-u2f to secure the login to a computer while
storing the mapping file in an encrypted home directory, will result
in the impossibility of logging into the system. The partition is
decrypted after login and the mapping file can not be accessed.
== Central authorization mapping
Create a file e.g. `/etc/u2f_mappings`., The file must contain
a user name, the number of registered Yubikeys and the information
obtained during the registration procedure.
The mappings should look like this, one per line:
<username1>:<KeyHandle1>,<UserKey1>:<KeyHandle2>,<UserKey2>:...
<username2>:<KeyHandle1>,<UserKey1>:<KeyHandle2>,<UserKey2>:...
Now add `authfile=/etc/u2f_mappings` to your PAM configuration line, so it
looks like:
auth sufficient pam_u2f.so authfile=/etc/u2f_mappings
If you do not set the `openasuser` setting, the authfile will be opened
and parsed as `root` so make sure it has the correct owner and
permissions set.
IMPORTANT: On dynamics networks (e.g. where hostnames are set by DHCP),
users should not rely on the default origin and appid ("pam://$HOSTNAME")
but set those parameters explicitly to the same value.
[[individualAuth]]
== Individual authorization mapping by user
Each user creates a `.config/Yubico/u2f_keys` (default) file inside their
home directory and places the mapping in that file. You may want to specify
a different per user file (relative to the users' home dir), i.e.
`.ssh/u2f_keys`. Bear in mind, setting an absolute path here is possible although
very likely a fragile setup, and probably not exhibiting the intended behaviour.
The file must have only one line:
<username>:<KeyHandle1>,<UserKey1>:<KeyHandle2>,<UserKey2>:...
This is much the same concept as the SSH authorized_keys file.
In this case, pam-u2f will drop privileges and read the mapping file
as that user. This happens regardless of the `openasuser` option being
set.
Note that if you set the XDG_CONFIG_HOME variable, privileges will not
be dropped by default. Consider also setting `openasuser` in that case.
[[registration]]
Obtaining key-handles and public keys
-------------------------------------
In order to obtain the required information for the authentication procedure,
a token should be first registered. This can be done by using the command line
configuration tool provided with the module:
----
$ pamu2fcfg -uusername -opam://myorigin -ipam://myappid
----
the tool will register a connected token by using the specified origin and
appid. If neither are specified they will default to +pam://$HOSTNAME+.
During the U2F registration, the user is required to touch the token.
On success the tool prints to standard output a configuration line that
can be directly used with the module. For additional information on the
tool read the relative manpage (+man pamu2fcfg+)
[[devices]]
Multiple Devices
----------------
Multiple devices are supported. If more than one device is specified,
authentication against them is attempted sequentially as they are defined
in the configuration file of the module. If during an authentication
attempt a connected device is removed or a new device is plugged in,
the authentication restarts from the top of the list.

12
external/bsd/pam-u2f/dist/autogen.sh vendored Executable file
View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -e
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
main() {
autoreconf --install
}
pushd "$DIR" &>/dev/null
main "$@"
popd &>/dev/null

108
external/bsd/pam-u2f/dist/b64.c vendored Normal file
View File

@ -0,0 +1,108 @@
/*
* Copyright (C) 2018 Yubico AB - See COPYING
*/
#include <openssl/bio.h>
#include <openssl/evp.h>
#include <stdint.h>
#include <string.h>
#include "b64.h"
int b64_encode(const void *ptr, size_t len, char **out) {
BIO *bio_b64 = NULL;
BIO *bio_mem = NULL;
char *b64_ptr = NULL;
long b64_len;
int n;
int ok = 0;
if (ptr == NULL || out == NULL || len > INT_MAX)
return (0);
*out = NULL;
bio_b64 = BIO_new(BIO_f_base64());
if (bio_b64 == NULL)
goto fail;
bio_mem = BIO_new(BIO_s_mem());
if (bio_mem == NULL)
goto fail;
BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL);
BIO_push(bio_b64, bio_mem);
n = BIO_write(bio_b64, ptr, (int) len);
if (n < 0 || (size_t) n != len)
goto fail;
if (BIO_flush(bio_b64) < 0)
goto fail;
b64_len = BIO_get_mem_data(bio_b64, &b64_ptr);
if (b64_len < 0 || (size_t) b64_len == SIZE_MAX || b64_ptr == NULL)
goto fail;
*out = calloc(1, (size_t) b64_len + 1);
if (*out == NULL)
goto fail;
memcpy(*out, b64_ptr, (size_t) b64_len);
ok = 1;
fail:
BIO_free(bio_b64);
BIO_free(bio_mem);
return (ok);
}
int b64_decode(const char *in, void **ptr, size_t *len) {
BIO *bio_mem = NULL;
BIO *bio_b64 = NULL;
size_t alloc_len;
int n;
int ok = 0;
if (in == NULL || ptr == NULL || len == NULL || strlen(in) > INT_MAX)
return (0);
*ptr = NULL;
*len = 0;
bio_b64 = BIO_new(BIO_f_base64());
if (bio_b64 == NULL)
goto fail;
bio_mem = BIO_new_mem_buf((void *) in, -1);
if (bio_mem == NULL)
goto fail;
BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL);
BIO_push(bio_b64, bio_mem);
alloc_len = strlen(in);
*ptr = calloc(1, alloc_len);
if (*ptr == NULL)
goto fail;
n = BIO_read(bio_b64, *ptr, (int) alloc_len);
if (n < 0 || BIO_eof(bio_b64) == 0)
goto fail;
*len = (size_t) n;
ok = 1;
fail:
BIO_free(bio_b64);
BIO_free(bio_mem);
if (!ok) {
free(*ptr);
*ptr = NULL;
*len = 0;
}
return (ok);
}

11
external/bsd/pam-u2f/dist/b64.h vendored Normal file
View File

@ -0,0 +1,11 @@
/*
* Copyright (C) 2018 Yubico AB - See COPYING
*/
#ifndef B64_H
#define B64_H
int b64_encode(const void *, size_t, char **);
int b64_decode(const char *, void **, size_t *);
#endif /* B64_H */

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
source $BUILDROOT/build-aux/ci/build-linux.sh

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
source $BUILDROOT/build-aux/ci/build-linux.sh

View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
set +x
source $BUILDROOT/build-aux/ci/format-code.sh "$(git rev-parse HEAD~)"
set -x
source $BUILDROOT/build-aux/ci/build-linux.sh

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
source $BUILDROOT/build-aux/ci/build-linux.sh

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
source $BUILDROOT/build-aux/ci/build-linux.sh

View File

@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
pushd "$BUILDROOT" &>/dev/null
./autogen.sh
./configure --disable-silent-rules --disable-man
make check
popd &>/dev/null

View File

@ -0,0 +1,30 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
pushd "/tmp" &>/dev/null
# Build and install libcbor
git clone git://github.com/pjk/libcbor
pushd "/tmp/libcbor" &>/dev/null
git checkout v0.5.0
cmake -Bbuild -H.
cmake --build build -- --jobs=2 VERBOSE=1
sudo make -C build install
popd &>/dev/null
# Build and install libfido2
export PKG_CONFIG_PATH=/usr/local/opt/openssl@1.1/lib/pkgconfig
git clone git://github.com/Yubico/libfido2
pushd "/tmp/libfido2" &>/dev/null
cmake -Bbuild -H.
cmake --build build -- --jobs=2 VERBOSE=1
sudo make -C build install
popd &>/dev/null
popd &>/dev/null
pushd "$BUILDROOT" &>/dev/null
./autogen.sh
./configure --disable-silent-rules --disable-man
make
popd &>/dev/null

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
source $BUILDROOT/build-aux/ci/build-osx.sh

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
source $BUILDROOT/build-aux/ci/build-osx.sh

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
source $BUILDROOT/build-aux/ci/build-linux.sh

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
source $BUILDROOT/build-aux/ci/build-linux.sh

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
source $BUILDROOT/build-aux/ci/build-linux.sh

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
source $BUILDROOT/build-aux/ci/build-linux.sh

View File

@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -ex
BUILDROOT="$(git rev-parse --show-toplevel)"
source $BUILDROOT/build-aux/ci/build-linux.sh

View File

@ -0,0 +1,38 @@
#!/bin/bash
#
# Inspired by https://github.com/antiagainst/SPIRV-Tools/commit/c4f1bf8ddf7764b7c11fed1ce18ceb1d36b2eaf6
#
# Script to determine if source code in a diff is properly formatted.
# On Travis it uses the commit range of the PR or push, otherwise it uses a provided range
# Exits with non 0 exit code if formatting is needed.
#
# This script assumes to be invoked at the project root directory.
COMMIT_RANGE="${TRAVIS_COMMIT_RANGE:-$1}"
if [ -z "${COMMIT_RANGE}" ]; then
>&2 echo "Empty commit range, missing parameter"
return 0
fi
>&2 echo "Commit range $COMMIT_RANGE"
FILES_TO_CHECK="$(git diff --name-only "$COMMIT_RANGE" | grep -e '\.c$' -e '\.h$' || true)"
CFV="${CLANG_FORMAT_VERSION:--6.0}"
if [ -z "${FILES_TO_CHECK}" ]; then
>&2 echo "No source code to check for formatting"
return 0
fi
FORMAT_DIFF=$(git diff -U0 ${COMMIT_RANGE} -- ${FILES_TO_CHECK} | clang-format-diff$CFV -p1)
if [ -z "${FORMAT_DIFF}" ]; then
>&2 echo "All source code in the diff is properly formatted"
return 0
else
>&2 echo -e "Found formatting errors\n"
echo "${FORMAT_DIFF}"
>&2 echo -e "\nYou can save the diff above and apply it with 'git apply -p0 my_diff'"
exit 1
fi

114
external/bsd/pam-u2f/dist/configure.ac vendored Normal file
View File

@ -0,0 +1,114 @@
# Copyright (C) 2014-2019 Yubico AB
AC_PREREQ([2.65])
AC_INIT([pam_u2f], [1.0.9], [https://github.com/Yubico/pam-u2f/issues],
[pam_u2f], [https://developers.yubico.com/pam-u2f/])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_HOST
AM_INIT_AUTOMAKE([1.11 foreign subdir-objects])
AM_SILENT_RULES([yes])
AM_MAINTAINER_MODE
AC_USE_SYSTEM_EXTENSIONS
AM_PROG_CC_C_O
AM_PROG_AR
AC_LIBTOOL_WIN32_DLL
AC_DISABLE_STATIC
AC_PROG_LIBTOOL
AC_PROG_CC_STDC
AC_ARG_ENABLE([man],
[AS_HELP_STRING([--disable-man], [Disable man page generation])],
[:],
[enable_man=yes]
)
AS_IF([test "$enable_man" = "yes"],
[AM_MISSING_PROG([A2X], a2x, $missing_dir)]
)
AM_CONDITIONAL([ENABLE_MAN], [test "$enable_man" = "yes"])
AC_CHECK_HEADERS([security/pam_appl.h], [],
[AC_MSG_ERROR([[PAM header files not found, install libpam-dev.]])])
AC_CHECK_HEADERS([security/pam_modules.h security/_pam_macros.h security/pam_modutil.h], [], [],
[#include <sys/types.h>
#include <security/pam_appl.h>])
AC_CHECK_LIB([pam], [pam_start])
AC_SEARCH_LIBS([pam_modutil_drop_priv], ["pam"], [AC_DEFINE([HAVE_PAM_MODUTIL_DROP_PRIV], [1])])
case "$host" in
*darwin*) PAMDIR="/usr/lib/pam";;
*linux*) PAMDIR="/lib/x86_64-linux-gnu/security";;
*) PAMDIR="/usr/lib"
esac
AC_ARG_WITH(pam-dir,
AC_HELP_STRING([--with-pam-dir=DIR], [Where to install the PAM module]), [
case "${withval}" in
/*) PAMDIR="${withval}";;
./*|../*) AC_MSG_ERROR(Bad value for --with-pam-dir);;
*);;
esac
])
AC_SUBST(PAMDIR, "$PAMDIR")
PKG_CHECK_MODULES([LIBCRYPTO], [libcrypto], [], [])
PKG_CHECK_MODULES([LIBFIDO2], [libfido2 >= 1.2.0], [], [])
# Check for secure_getenv, readpassphrase, explicit_bzero, and memset_s
am_save_CFLAGS="$CFLAGS"
am_save_LIBS="$LIBS"
CFLAGS="$CFLAGS"
LIBS="$LIBS"
AC_CHECK_FUNCS([secure_getenv readpassphrase explicit_bzero memset_s])
CFLAGS=$am_save_CFLAGS
LIBS=$am_save_LIBS
AC_ARG_VAR([CWFLAGS], [Warning flags])
AX_CHECK_COMPILE_FLAG([-Wall], [CWFLAGS="-Wall"])
AX_CHECK_COMPILE_FLAG([-Wextra], [CWFLAGS="$CWFLAGS -Wextra"])
AX_CHECK_COMPILE_FLAG([-Wconversion], [CWFLAGS="$CWFLAGS -Wconversion"])
# Because pam headers are doing sign-conversion, see PAM_MODUTIL_DEF_PRIVS in pam_modutil.h
AX_CHECK_COMPILE_FLAG([-Wconversion], [CWFLAGS="$CWFLAGS -Wno-sign-conversion"])
AX_CHECK_COMPILE_FLAG([-Wpedantic], [CWFLAGS="$CWFLAGS -Wpedantic"])
AX_CHECK_COMPILE_FLAG([-Wformat=2], [CWFLAGS="$CWFLAGS -Wformat=2"])
AX_CHECK_COMPILE_FLAG([-Wstrict-prototypes], [CWFLAGS="$CWFLAGS -Wstrict-prototypes"])
AX_CHECK_COMPILE_FLAG([-Wmissing-declarations], [CWFLAGS="$CWFLAGS -Wmissing-declarations"])
AX_CHECK_COMPILE_FLAG([-Wmissing-prototypes], [CWFLAGS="$CWFLAGS -Wmissing-prototypes"])
AX_CHECK_COMPILE_FLAG([-Wnull-dereference], [CWFLAGS="$CWFLAGS -Wnull-dereference"])
AX_CHECK_COMPILE_FLAG([-Wshadow], [CWFLAGS="$CWFLAGS -Wshadow"])
AX_CHECK_COMPILE_FLAG([-Wpointer-arith], [CWFLAGS="$CWFLAGS -Wpointer-arith"])
AC_ARG_VAR([CSFLAGS], [Warning suppression flags])
AX_CHECK_COMPILE_FLAG([-Wno-unused-but-set-variable], [CSFLAGS="-Wno-unused-but-set-variable"])
AC_CONFIG_FILES([
Makefile
pamu2fcfg/Makefile
tests/Makefile
])
AC_OUTPUT
AC_MSG_NOTICE([Summary of build options:
Version: ${VERSION}
Host type: ${host}
Install prefix: ${prefix}
Compiler: ${CC}
CFLAGS: ${CFLAGS}
CWFLAGS: ${CWFLAGS}
CSFLAGS: ${CSFLAGS}
Library types: Shared=${enable_shared}, Static=${enable_static}
LIBFIDO2 CFLAGS: $LIBFIDO2_CFLAGS
LIBFIDO2 LIBS: $LIBFIDO2_LIBS
LIBCRYPTO CFLAGS: $LIBCRYPTO_CFLAGS
LIBCRYPTO LIBS: $LIBCRYPTO_LIBS
PAMDIR: $PAMDIR
])

131
external/bsd/pam-u2f/dist/drop_privs.c vendored Normal file
View File

@ -0,0 +1,131 @@
/* Written by Ricky Zhou <ricky@fedoraproject.org>
* Fredrik Thulin <fredrik@yubico.com> implemented pam_modutil_drop_priv
*
* Copyright (c) 2011-2014 Yubico AB
* Copyright (c) 2011 Ricky Zhou <ricky@fedoraproject.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef HAVE_PAM_MODUTIL_DROP_PRIV
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "drop_privs.h"
#include "util.h"
#ifdef HAVE_SECURITY_PAM_APPL_H
#include <security/pam_appl.h>
#endif
#ifdef HAVE_SECURITY_PAM_MODULES_H
#include <security/pam_modules.h>
#endif
int pam_modutil_drop_priv(pam_handle_t *pamh, struct _ykpam_privs *privs,
struct passwd *pw) {
privs->saved_euid = geteuid();
privs->saved_egid = getegid();
if ((privs->saved_euid == pw->pw_uid) && (privs->saved_egid == pw->pw_gid)) {
D(privs->debug_file, "Privilges already dropped, pretend it is all right");
return 0;
}
privs->saved_groups_length = getgroups(0, NULL);
if (privs->saved_groups_length < 0) {
D(privs->debug_file, "getgroups: %s", strerror(errno));
return -1;
}
if (privs->saved_groups_length > SAVED_GROUPS_MAX_LEN) {
D(privs->debug_file, "too many groups, limiting.");
privs->saved_groups_length = SAVED_GROUPS_MAX_LEN;
}
if (privs->saved_groups_length > 0) {
if (getgroups(privs->saved_groups_length, privs->saved_groups) < 0) {
D(privs->debug_file, "getgroups: %s", strerror(errno));
goto free_out;
}
}
if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
D(privs->debug_file, "initgroups: %s", strerror(errno));
goto free_out;
}
if (setegid(pw->pw_gid) < 0) {
D(privs->debug_file, "setegid: %s", strerror(errno));
goto free_out;
}
if (seteuid(pw->pw_uid) < 0) {
D(privs->debug_file, "seteuid: %s", strerror(errno));
goto free_out;
}
return 0;
free_out:
return -1;
}
int pam_modutil_regain_priv(pam_handle_t *pamh, struct _ykpam_privs *privs) {
if ((privs->saved_euid == geteuid()) && (privs->saved_egid == getegid())) {
D(privs->debug_file,
"Privilges already as requested, pretend it is all right");
return 0;
}
if (seteuid(privs->saved_euid) < 0) {
D(privs->debug_file, "seteuid: %s", strerror(errno));
return -1;
}
if (setegid(privs->saved_egid) < 0) {
D(privs->debug_file, "setegid: %s", strerror(errno));
return -1;
}
if (setgroups(privs->saved_groups_length, privs->saved_groups) < 0) {
D(privs->debug_file, "setgroups: %s", strerror(errno));
return -1;
}
return 0;
}
#else
// drop_privs.c:124: warning: ISO C forbids an empty translation unit
// [-Wpedantic]
typedef int make_iso_compilers_happy;
#endif // HAVE_PAM_MODUTIL_DROP_PRIV

66
external/bsd/pam-u2f/dist/drop_privs.h vendored Normal file
View File

@ -0,0 +1,66 @@
/* Copyright (c) 2011-2014 Yubico AB
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __PAM_U2F_DROP_PRIVS_H_INCLUDED__
#define __PAM_U2F_DROP_PRIVS_H_INCLUDED__
#ifdef HAVE_PAM_MODUTIL_DROP_PRIV
#include <security/pam_modutil.h>
#else
#include <pwd.h>
#include <stdio.h>
#ifdef HAVE_SECURITY_PAM_APPL_H
#include <security/pam_appl.h>
#endif
#ifdef HAVE_SECURITY_PAM_MODULES_H
#include <security/pam_modules.h>
#endif
#define SAVED_GROUPS_MAX_LEN 64 /* as pam_modutil.. */
struct _ykpam_privs {
uid_t saved_euid;
gid_t saved_egid;
gid_t *saved_groups;
int saved_groups_length;
FILE *debug_file;
};
#define PAM_MODUTIL_DEF_PRIVS(n) \
gid_t n##_saved_groups[SAVED_GROUPS_MAX_LEN]; \
struct _ykpam_privs n = {-1, -1, n##_saved_groups, SAVED_GROUPS_MAX_LEN, \
cfg->debug_file}
int pam_modutil_drop_priv(pam_handle_t *, struct _ykpam_privs *,
struct passwd *);
int pam_modutil_regain_priv(pam_handle_t *, struct _ykpam_privs *);
#endif
#endif

View File

@ -0,0 +1,53 @@
/* OPENBSD ORIGINAL: lib/libc/string/explicit_bzero.c */
/* $OpenBSD: explicit_bzero.c,v 1.1 2014/01/22 21:06:45 tedu Exp $ */
/*
* Public domain.
* Written by Ted Unangst
*/
#include <string.h>
/*
* explicit_bzero - don't let the compiler optimize away bzero
*/
#ifndef HAVE_EXPLICIT_BZERO
#include "util.h"
#ifdef HAVE_MEMSET_S
void explicit_bzero(void *p, size_t n) {
if (n == 0)
return;
(void) memset_s(p, n, 0, n);
}
#else /* HAVE_MEMSET_S */
/*
* Indirect bzero through a volatile pointer to hopefully avoid
* dead-store optimisation eliminating the call.
*/
static void (*volatile ssh_bzero)(void *, size_t) = bzero;
void explicit_bzero(void *p, size_t n) {
if (n == 0)
return;
/*
* clang -fsanitize=memory needs to intercept memset-like functions
* to correctly detect memory initialisation. Make sure one is called
* directly since our indirection trick above successfully confuses it.
*/
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
memset(p, 0, n);
#endif
#endif
ssh_bzero(p, n);
}
#endif /* HAVE_MEMSET_S */
#endif /* HAVE_EXPLICIT_BZERO */

View File

@ -0,0 +1,73 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS])
#
# DESCRIPTION
#
# Check whether the given FLAG works with the current language's compiler
# or gives an error. (Warnings, however, are ignored)
#
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
# success/failure.
#
# If EXTRA-FLAGS is defined, it is added to the current language's default
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
# force the compiler to issue an error when a bad flag is given.
#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
#
# 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 3 of the License, or (at your
# option) any later version.
#
# 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.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 4
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
AC_TRY_LINK([#include <stdio.h>],
[char x[42U], fodder = 0;if (fodder > -1000 && fgets(x,1000,stdin)) puts(x)],
[AS_VAR_SET(CACHEVAR,[yes])],
[AS_VAR_SET(CACHEVAR,[no])])
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
AS_VAR_IF(CACHEVAR,yes,
[m4_default([$2], :)],
[m4_default([$3], :)])
AS_VAR_POPDEF([CACHEVAR])dnl
])dnl AX_CHECK_COMPILE_FLAGS

110
external/bsd/pam-u2f/dist/m4/lib-ld.m4 vendored Normal file
View File

@ -0,0 +1,110 @@
# lib-ld.m4 serial 4 (gettext-0.18)
dnl Copyright (C) 1996-2003, 2009 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl Subroutines of libtool.m4,
dnl with replacements s/AC_/AC_LIB/ and s/lt_cv/acl_cv/ to avoid collision
dnl with libtool.m4.
dnl From libtool-1.4. Sets the variable with_gnu_ld to yes or no.
AC_DEFUN([AC_LIB_PROG_LD_GNU],
[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld],
[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
case `$LD -v 2>&1 </dev/null` in
*GNU* | *'with BFD'*)
acl_cv_prog_gnu_ld=yes ;;
*)
acl_cv_prog_gnu_ld=no ;;
esac])
with_gnu_ld=$acl_cv_prog_gnu_ld
])
dnl From libtool-1.4. Sets the variable LD.
AC_DEFUN([AC_LIB_PROG_LD],
[AC_ARG_WITH([gnu-ld],
[ --with-gnu-ld assume the C compiler uses GNU ld [default=no]],
test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
AC_REQUIRE([AC_PROG_CC])dnl
AC_REQUIRE([AC_CANONICAL_HOST])dnl
# Prepare PATH_SEPARATOR.
# The user is always right.
if test "${PATH_SEPARATOR+set}" != set; then
echo "#! /bin/sh" >conf$$.sh
echo "exit 0" >>conf$$.sh
chmod +x conf$$.sh
if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then
PATH_SEPARATOR=';'
else
PATH_SEPARATOR=:
fi
rm -f conf$$.sh
fi
ac_prog=ld
if test "$GCC" = yes; then
# Check if gcc -print-prog-name=ld gives a path.
AC_MSG_CHECKING([for ld used by GCC])
case $host in
*-*-mingw*)
# gcc leaves a trailing carriage return which upsets mingw
ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
*)
ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
esac
case $ac_prog in
# Accept absolute paths.
[[\\/]* | [A-Za-z]:[\\/]*)]
[re_direlt='/[^/][^/]*/\.\./']
# Canonicalize the path of ld
ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
done
test -z "$LD" && LD="$ac_prog"
;;
"")
# If it fails, then pretend we aren't using GCC.
ac_prog=ld
;;
*)
# If it is relative, then search for the first ld in PATH.
with_gnu_ld=unknown
;;
esac
elif test "$with_gnu_ld" = yes; then
AC_MSG_CHECKING([for GNU ld])
else
AC_MSG_CHECKING([for non-GNU ld])
fi
AC_CACHE_VAL([acl_cv_path_LD],
[if test -z "$LD"; then
IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
for ac_dir in $PATH; do
test -z "$ac_dir" && ac_dir=.
if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
acl_cv_path_LD="$ac_dir/$ac_prog"
# Check to see if the program is GNU ld. I'd rather use --version,
# but apparently some GNU ld's only accept -v.
# Break only if it was the GNU/non-GNU ld that we prefer.
case `"$acl_cv_path_LD" -v 2>&1 < /dev/null` in
*GNU* | *'with BFD'*)
test "$with_gnu_ld" != no && break ;;
*)
test "$with_gnu_ld" != yes && break ;;
esac
fi
done
IFS="$ac_save_ifs"
else
acl_cv_path_LD="$LD" # Let the user override the test with a path.
fi])
LD="$acl_cv_path_LD"
if test -n "$LD"; then
AC_MSG_RESULT([$LD])
else
AC_MSG_RESULT([no])
fi
test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
AC_LIB_PROG_LD_GNU
])

758
external/bsd/pam-u2f/dist/m4/lib-link.m4 vendored Normal file
View File

@ -0,0 +1,758 @@
# lib-link.m4 serial 18 (gettext-0.18)
dnl Copyright (C) 2001-2009 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Bruno Haible.
AC_PREREQ([2.54])
dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
dnl the libraries corresponding to explicit and implicit dependencies.
dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
dnl augments the CPPFLAGS variable.
dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
AC_DEFUN([AC_LIB_LINKFLAGS],
[
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
AC_REQUIRE([AC_LIB_RPATH])
pushdef([Name],[translit([$1],[./-], [___])])
pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
AC_LIB_LINKFLAGS_BODY([$1], [$2])
ac_cv_lib[]Name[]_libs="$LIB[]NAME"
ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX"
])
LIB[]NAME="$ac_cv_lib[]Name[]_libs"
LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix"
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
AC_SUBST([LIB]NAME)
AC_SUBST([LTLIB]NAME)
AC_SUBST([LIB]NAME[_PREFIX])
dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
dnl results of this search when this library appears as a dependency.
HAVE_LIB[]NAME=yes
popdef([NAME])
popdef([Name])
])
dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode)
dnl searches for libname and the libraries corresponding to explicit and
dnl implicit dependencies, together with the specified include files and
dnl the ability to compile and link the specified testcode. If found, it
dnl sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME} and
dnl LTLIB${NAME} variables and augments the CPPFLAGS variable, and
dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
[
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
AC_REQUIRE([AC_LIB_RPATH])
pushdef([Name],[translit([$1],[./-], [___])])
pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
dnl accordingly.
AC_LIB_LINKFLAGS_BODY([$1], [$2])
dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
dnl because if the user has installed lib[]Name and not disabled its use
dnl via --without-lib[]Name-prefix, he wants to use it.
ac_save_CPPFLAGS="$CPPFLAGS"
AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
ac_save_LIBS="$LIBS"
LIBS="$LIBS $LIB[]NAME"
AC_TRY_LINK([$3], [$4], [ac_cv_lib[]Name=yes], [ac_cv_lib[]Name=no])
LIBS="$ac_save_LIBS"
])
if test "$ac_cv_lib[]Name" = yes; then
HAVE_LIB[]NAME=yes
AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the $1 library.])
AC_MSG_CHECKING([how to link with lib[]$1])
AC_MSG_RESULT([$LIB[]NAME])
else
HAVE_LIB[]NAME=no
dnl If $LIB[]NAME didn't lead to a usable library, we don't need
dnl $INC[]NAME either.
CPPFLAGS="$ac_save_CPPFLAGS"
LIB[]NAME=
LTLIB[]NAME=
LIB[]NAME[]_PREFIX=
fi
AC_SUBST([HAVE_LIB]NAME)
AC_SUBST([LIB]NAME)
AC_SUBST([LTLIB]NAME)
AC_SUBST([LIB]NAME[_PREFIX])
popdef([NAME])
popdef([Name])
])
dnl Determine the platform dependent parameters needed to use rpath:
dnl acl_libext,
dnl acl_shlibext,
dnl acl_hardcode_libdir_flag_spec,
dnl acl_hardcode_libdir_separator,
dnl acl_hardcode_direct,
dnl acl_hardcode_minus_L.
AC_DEFUN([AC_LIB_RPATH],
[
dnl Tell automake >= 1.10 to complain if config.rpath is missing.
m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS
AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld
AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host
AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [
CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
. ./conftest.sh
rm -f ./conftest.sh
acl_cv_rpath=done
])
wl="$acl_cv_wl"
acl_libext="$acl_cv_libext"
acl_shlibext="$acl_cv_shlibext"
acl_libname_spec="$acl_cv_libname_spec"
acl_library_names_spec="$acl_cv_library_names_spec"
acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
acl_hardcode_direct="$acl_cv_hardcode_direct"
acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
dnl Determine whether the user wants rpath handling at all.
AC_ARG_ENABLE([rpath],
[ --disable-rpath do not hardcode runtime library paths],
:, enable_rpath=yes)
])
dnl AC_LIB_FROMPACKAGE(name, package)
dnl declares that libname comes from the given package. The configure file
dnl will then not have a --with-libname-prefix option but a
dnl --with-package-prefix option. Several libraries can come from the same
dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar
dnl macro call that searches for libname.
AC_DEFUN([AC_LIB_FROMPACKAGE],
[
pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
define([acl_frompackage_]NAME, [$2])
popdef([NAME])
pushdef([PACK],[$2])
pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
define([acl_libsinpackage_]PACKUP,
m4_ifdef([acl_libsinpackage_]PACKUP, [acl_libsinpackage_]PACKUP[[, ]],)[lib$1])
popdef([PACKUP])
popdef([PACK])
])
dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
dnl the libraries corresponding to explicit and implicit dependencies.
dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found
dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
[
AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
pushdef([NAME],[translit([$1],[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])])
pushdef([PACKUP],[translit(PACK,[abcdefghijklmnopqrstuvwxyz./-],
[ABCDEFGHIJKLMNOPQRSTUVWXYZ___])])
pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])])
dnl Autoconf >= 2.61 supports dots in --with options.
pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[translit(PACK,[.],[_])],PACK)])
dnl By default, look in $includedir and $libdir.
use_additional=yes
AC_LIB_WITH_FINAL_PREFIX([
eval additional_includedir=\"$includedir\"
eval additional_libdir=\"$libdir\"
])
AC_ARG_WITH(P_A_C_K[-prefix],
[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib
--without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]],
[
if test "X$withval" = "Xno"; then
use_additional=no
else
if test "X$withval" = "X"; then
AC_LIB_WITH_FINAL_PREFIX([
eval additional_includedir=\"$includedir\"
eval additional_libdir=\"$libdir\"
])
else
additional_includedir="$withval/include"
additional_libdir="$withval/$acl_libdirstem"
if test "$acl_libdirstem2" != "$acl_libdirstem" \
&& ! test -d "$withval/$acl_libdirstem"; then
additional_libdir="$withval/$acl_libdirstem2"
fi
fi
fi
])
dnl Search the library and its dependencies in $additional_libdir and
dnl $LDFLAGS. Using breadth-first-seach.
LIB[]NAME=
LTLIB[]NAME=
INC[]NAME=
LIB[]NAME[]_PREFIX=
rpathdirs=
ltrpathdirs=
names_already_handled=
names_next_round='$1 $2'
while test -n "$names_next_round"; do
names_this_round="$names_next_round"
names_next_round=
for name in $names_this_round; do
already_handled=
for n in $names_already_handled; do
if test "$n" = "$name"; then
already_handled=yes
break
fi
done
if test -z "$already_handled"; then
names_already_handled="$names_already_handled $name"
dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
dnl or AC_LIB_HAVE_LINKFLAGS call.
uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./-|ABCDEFGHIJKLMNOPQRSTUVWXYZ___|'`
eval value=\"\$HAVE_LIB$uppername\"
if test -n "$value"; then
if test "$value" = yes; then
eval value=\"\$LIB$uppername\"
test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
eval value=\"\$LTLIB$uppername\"
test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
else
dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
dnl that this library doesn't exist. So just drop it.
:
fi
else
dnl Search the library lib$name in $additional_libdir and $LDFLAGS
dnl and the already constructed $LIBNAME/$LTLIBNAME.
found_dir=
found_la=
found_so=
found_a=
eval libname=\"$acl_libname_spec\" # typically: libname=lib$name
if test -n "$acl_shlibext"; then
shrext=".$acl_shlibext" # typically: shrext=.so
else
shrext=
fi
if test $use_additional = yes; then
dir="$additional_libdir"
dnl The same code as in the loop below:
dnl First look for a shared library.
if test -n "$acl_shlibext"; then
if test -f "$dir/$libname$shrext"; then
found_dir="$dir"
found_so="$dir/$libname$shrext"
else
if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
ver=`(cd "$dir" && \
for f in "$libname$shrext".*; do echo "$f"; done \
| sed -e "s,^$libname$shrext\\\\.,," \
| sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
| sed 1q ) 2>/dev/null`
if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
found_dir="$dir"
found_so="$dir/$libname$shrext.$ver"
fi
else
eval library_names=\"$acl_library_names_spec\"
for f in $library_names; do
if test -f "$dir/$f"; then
found_dir="$dir"
found_so="$dir/$f"
break
fi
done
fi
fi
fi
dnl Then look for a static library.
if test "X$found_dir" = "X"; then
if test -f "$dir/$libname.$acl_libext"; then
found_dir="$dir"
found_a="$dir/$libname.$acl_libext"
fi
fi
if test "X$found_dir" != "X"; then
if test -f "$dir/$libname.la"; then
found_la="$dir/$libname.la"
fi
fi
fi
if test "X$found_dir" = "X"; then
for x in $LDFLAGS $LTLIB[]NAME; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
case "$x" in
-L*)
dir=`echo "X$x" | sed -e 's/^X-L//'`
dnl First look for a shared library.
if test -n "$acl_shlibext"; then
if test -f "$dir/$libname$shrext"; then
found_dir="$dir"
found_so="$dir/$libname$shrext"
else
if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
ver=`(cd "$dir" && \
for f in "$libname$shrext".*; do echo "$f"; done \
| sed -e "s,^$libname$shrext\\\\.,," \
| sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
| sed 1q ) 2>/dev/null`
if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
found_dir="$dir"
found_so="$dir/$libname$shrext.$ver"
fi
else
eval library_names=\"$acl_library_names_spec\"
for f in $library_names; do
if test -f "$dir/$f"; then
found_dir="$dir"
found_so="$dir/$f"
break
fi
done
fi
fi
fi
dnl Then look for a static library.
if test "X$found_dir" = "X"; then
if test -f "$dir/$libname.$acl_libext"; then
found_dir="$dir"
found_a="$dir/$libname.$acl_libext"
fi
fi
if test "X$found_dir" != "X"; then
if test -f "$dir/$libname.la"; then
found_la="$dir/$libname.la"
fi
fi
;;
esac
if test "X$found_dir" != "X"; then
break
fi
done
fi
if test "X$found_dir" != "X"; then
dnl Found the library.
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
if test "X$found_so" != "X"; then
dnl Linking with a shared library. We attempt to hardcode its
dnl directory into the executable's runpath, unless it's the
dnl standard /usr/lib.
if test "$enable_rpath" = no \
|| test "X$found_dir" = "X/usr/$acl_libdirstem" \
|| test "X$found_dir" = "X/usr/$acl_libdirstem2"; then
dnl No hardcoding is needed.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
else
dnl Use an explicit option to hardcode DIR into the resulting
dnl binary.
dnl Potentially add DIR to ltrpathdirs.
dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
haveit=
for x in $ltrpathdirs; do
if test "X$x" = "X$found_dir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
ltrpathdirs="$ltrpathdirs $found_dir"
fi
dnl The hardcoding into $LIBNAME is system dependent.
if test "$acl_hardcode_direct" = yes; then
dnl Using DIR/libNAME.so during linking hardcodes DIR into the
dnl resulting binary.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
else
if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
dnl Use an explicit option to hardcode DIR into the resulting
dnl binary.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
dnl Potentially add DIR to rpathdirs.
dnl The rpathdirs will be appended to $LIBNAME at the end.
haveit=
for x in $rpathdirs; do
if test "X$x" = "X$found_dir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
rpathdirs="$rpathdirs $found_dir"
fi
else
dnl Rely on "-L$found_dir".
dnl But don't add it if it's already contained in the LDFLAGS
dnl or the already constructed $LIBNAME
haveit=
for x in $LDFLAGS $LIB[]NAME; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X-L$found_dir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
fi
if test "$acl_hardcode_minus_L" != no; then
dnl FIXME: Not sure whether we should use
dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
dnl here.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
else
dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH
dnl here, because this doesn't fit in flags passed to the
dnl compiler. So give up. No hardcoding. This affects only
dnl very old systems.
dnl FIXME: Not sure whether we should use
dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
dnl here.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
fi
fi
fi
fi
else
if test "X$found_a" != "X"; then
dnl Linking with a static library.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
else
dnl We shouldn't come here, but anyway it's good to have a
dnl fallback.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
fi
fi
dnl Assume the include files are nearby.
additional_includedir=
case "$found_dir" in
*/$acl_libdirstem | */$acl_libdirstem/)
basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
if test "$name" = '$1'; then
LIB[]NAME[]_PREFIX="$basedir"
fi
additional_includedir="$basedir/include"
;;
*/$acl_libdirstem2 | */$acl_libdirstem2/)
basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'`
if test "$name" = '$1'; then
LIB[]NAME[]_PREFIX="$basedir"
fi
additional_includedir="$basedir/include"
;;
esac
if test "X$additional_includedir" != "X"; then
dnl Potentially add $additional_includedir to $INCNAME.
dnl But don't add it
dnl 1. if it's the standard /usr/include,
dnl 2. if it's /usr/local/include and we are using GCC on Linux,
dnl 3. if it's already present in $CPPFLAGS or the already
dnl constructed $INCNAME,
dnl 4. if it doesn't exist as a directory.
if test "X$additional_includedir" != "X/usr/include"; then
haveit=
if test "X$additional_includedir" = "X/usr/local/include"; then
if test -n "$GCC"; then
case $host_os in
linux* | gnu* | k*bsd*-gnu) haveit=yes;;
esac
fi
fi
if test -z "$haveit"; then
for x in $CPPFLAGS $INC[]NAME; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X-I$additional_includedir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
if test -d "$additional_includedir"; then
dnl Really add $additional_includedir to $INCNAME.
INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
fi
fi
fi
fi
fi
dnl Look for dependencies.
if test -n "$found_la"; then
dnl Read the .la file. It defines the variables
dnl dlname, library_names, old_library, dependency_libs, current,
dnl age, revision, installed, dlopen, dlpreopen, libdir.
save_libdir="$libdir"
case "$found_la" in
*/* | *\\*) . "$found_la" ;;
*) . "./$found_la" ;;
esac
libdir="$save_libdir"
dnl We use only dependency_libs.
for dep in $dependency_libs; do
case "$dep" in
-L*)
additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
dnl But don't add it
dnl 1. if it's the standard /usr/lib,
dnl 2. if it's /usr/local/lib and we are using GCC on Linux,
dnl 3. if it's already present in $LDFLAGS or the already
dnl constructed $LIBNAME,
dnl 4. if it doesn't exist as a directory.
if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \
&& test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then
haveit=
if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \
|| test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then
if test -n "$GCC"; then
case $host_os in
linux* | gnu* | k*bsd*-gnu) haveit=yes;;
esac
fi
fi
if test -z "$haveit"; then
haveit=
for x in $LDFLAGS $LIB[]NAME; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X-L$additional_libdir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
if test -d "$additional_libdir"; then
dnl Really add $additional_libdir to $LIBNAME.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
fi
fi
haveit=
for x in $LDFLAGS $LTLIB[]NAME; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X-L$additional_libdir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
if test -d "$additional_libdir"; then
dnl Really add $additional_libdir to $LTLIBNAME.
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
fi
fi
fi
fi
;;
-R*)
dir=`echo "X$dep" | sed -e 's/^X-R//'`
if test "$enable_rpath" != no; then
dnl Potentially add DIR to rpathdirs.
dnl The rpathdirs will be appended to $LIBNAME at the end.
haveit=
for x in $rpathdirs; do
if test "X$x" = "X$dir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
rpathdirs="$rpathdirs $dir"
fi
dnl Potentially add DIR to ltrpathdirs.
dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
haveit=
for x in $ltrpathdirs; do
if test "X$x" = "X$dir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
ltrpathdirs="$ltrpathdirs $dir"
fi
fi
;;
-l*)
dnl Handle this in the next round.
names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
;;
*.la)
dnl Handle this in the next round. Throw away the .la's
dnl directory; it is already contained in a preceding -L
dnl option.
names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
;;
*)
dnl Most likely an immediate library name.
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
;;
esac
done
fi
else
dnl Didn't find the library; assume it is in the system directories
dnl known to the linker and runtime loader. (All the system
dnl directories known to the linker should also be known to the
dnl runtime loader, otherwise the system is severely misconfigured.)
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
fi
fi
fi
done
done
if test "X$rpathdirs" != "X"; then
if test -n "$acl_hardcode_libdir_separator"; then
dnl Weird platform: only the last -rpath option counts, the user must
dnl pass all path elements in one option. We can arrange that for a
dnl single library, but not when more than one $LIBNAMEs are used.
alldirs=
for found_dir in $rpathdirs; do
alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
done
dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl.
acl_save_libdir="$libdir"
libdir="$alldirs"
eval flag=\"$acl_hardcode_libdir_flag_spec\"
libdir="$acl_save_libdir"
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
else
dnl The -rpath options are cumulative.
for found_dir in $rpathdirs; do
acl_save_libdir="$libdir"
libdir="$found_dir"
eval flag=\"$acl_hardcode_libdir_flag_spec\"
libdir="$acl_save_libdir"
LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
done
fi
fi
if test "X$ltrpathdirs" != "X"; then
dnl When using libtool, the option that works for both libraries and
dnl executables is -R. The -R options are cumulative.
for found_dir in $ltrpathdirs; do
LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
done
fi
popdef([P_A_C_K])
popdef([PACKLIBS])
popdef([PACKUP])
popdef([PACK])
popdef([NAME])
])
dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
dnl unless already present in VAR.
dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
dnl contains two or three consecutive elements that belong together.
AC_DEFUN([AC_LIB_APPENDTOVAR],
[
for element in [$2]; do
haveit=
for x in $[$1]; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X$element"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
[$1]="${[$1]}${[$1]:+ }$element"
fi
done
])
dnl For those cases where a variable contains several -L and -l options
dnl referring to unknown libraries and directories, this macro determines the
dnl necessary additional linker options for the runtime path.
dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL])
dnl sets LDADDVAR to linker options needed together with LIBSVALUE.
dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed,
dnl otherwise linking without libtool is assumed.
AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS],
[
AC_REQUIRE([AC_LIB_RPATH])
AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
$1=
if test "$enable_rpath" != no; then
if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
dnl Use an explicit option to hardcode directories into the resulting
dnl binary.
rpathdirs=
next=
for opt in $2; do
if test -n "$next"; then
dir="$next"
dnl No need to hardcode the standard /usr/lib.
if test "X$dir" != "X/usr/$acl_libdirstem" \
&& test "X$dir" != "X/usr/$acl_libdirstem2"; then
rpathdirs="$rpathdirs $dir"
fi
next=
else
case $opt in
-L) next=yes ;;
-L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'`
dnl No need to hardcode the standard /usr/lib.
if test "X$dir" != "X/usr/$acl_libdirstem" \
&& test "X$dir" != "X/usr/$acl_libdirstem2"; then
rpathdirs="$rpathdirs $dir"
fi
next= ;;
*) next= ;;
esac
fi
done
if test "X$rpathdirs" != "X"; then
if test -n ""$3""; then
dnl libtool is used for linking. Use -R options.
for dir in $rpathdirs; do
$1="${$1}${$1:+ }-R$dir"
done
else
dnl The linker is used for linking directly.
if test -n "$acl_hardcode_libdir_separator"; then
dnl Weird platform: only the last -rpath option counts, the user
dnl must pass all path elements in one option.
alldirs=
for dir in $rpathdirs; do
alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir"
done
acl_save_libdir="$libdir"
libdir="$alldirs"
eval flag=\"$acl_hardcode_libdir_flag_spec\"
libdir="$acl_save_libdir"
$1="$flag"
else
dnl The -rpath options are cumulative.
for dir in $rpathdirs; do
acl_save_libdir="$libdir"
libdir="$dir"
eval flag=\"$acl_hardcode_libdir_flag_spec\"
libdir="$acl_save_libdir"
$1="${$1}${$1:+ }$flag"
done
fi
fi
fi
fi
fi
AC_SUBST([$1])
])

View File

@ -0,0 +1,221 @@
# lib-prefix.m4 serial 6 (gettext-0.18)
dnl Copyright (C) 2001-2005, 2008 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Bruno Haible.
dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
dnl require excessive bracketing.
ifdef([AC_HELP_STRING],
[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
dnl to access previously installed libraries. The basic assumption is that
dnl a user will want packages to use other packages he previously installed
dnl with the same --prefix option.
dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
dnl libraries, but is otherwise very convenient.
AC_DEFUN([AC_LIB_PREFIX],
[
AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_HOST])
AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
dnl By default, look in $includedir and $libdir.
use_additional=yes
AC_LIB_WITH_FINAL_PREFIX([
eval additional_includedir=\"$includedir\"
eval additional_libdir=\"$libdir\"
])
AC_LIB_ARG_WITH([lib-prefix],
[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
--without-lib-prefix don't search for libraries in includedir and libdir],
[
if test "X$withval" = "Xno"; then
use_additional=no
else
if test "X$withval" = "X"; then
AC_LIB_WITH_FINAL_PREFIX([
eval additional_includedir=\"$includedir\"
eval additional_libdir=\"$libdir\"
])
else
additional_includedir="$withval/include"
additional_libdir="$withval/$acl_libdirstem"
fi
fi
])
if test $use_additional = yes; then
dnl Potentially add $additional_includedir to $CPPFLAGS.
dnl But don't add it
dnl 1. if it's the standard /usr/include,
dnl 2. if it's already present in $CPPFLAGS,
dnl 3. if it's /usr/local/include and we are using GCC on Linux,
dnl 4. if it doesn't exist as a directory.
if test "X$additional_includedir" != "X/usr/include"; then
haveit=
for x in $CPPFLAGS; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X-I$additional_includedir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
if test "X$additional_includedir" = "X/usr/local/include"; then
if test -n "$GCC"; then
case $host_os in
linux* | gnu* | k*bsd*-gnu) haveit=yes;;
esac
fi
fi
if test -z "$haveit"; then
if test -d "$additional_includedir"; then
dnl Really add $additional_includedir to $CPPFLAGS.
CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
fi
fi
fi
fi
dnl Potentially add $additional_libdir to $LDFLAGS.
dnl But don't add it
dnl 1. if it's the standard /usr/lib,
dnl 2. if it's already present in $LDFLAGS,
dnl 3. if it's /usr/local/lib and we are using GCC on Linux,
dnl 4. if it doesn't exist as a directory.
if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
haveit=
for x in $LDFLAGS; do
AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
if test "X$x" = "X-L$additional_libdir"; then
haveit=yes
break
fi
done
if test -z "$haveit"; then
if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
if test -n "$GCC"; then
case $host_os in
linux*) haveit=yes;;
esac
fi
fi
if test -z "$haveit"; then
if test -d "$additional_libdir"; then
dnl Really add $additional_libdir to $LDFLAGS.
LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
fi
fi
fi
fi
fi
])
dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
dnl acl_final_exec_prefix, containing the values to which $prefix and
dnl $exec_prefix will expand at the end of the configure script.
AC_DEFUN([AC_LIB_PREPARE_PREFIX],
[
dnl Unfortunately, prefix and exec_prefix get only finally determined
dnl at the end of configure.
if test "X$prefix" = "XNONE"; then
acl_final_prefix="$ac_default_prefix"
else
acl_final_prefix="$prefix"
fi
if test "X$exec_prefix" = "XNONE"; then
acl_final_exec_prefix='${prefix}'
else
acl_final_exec_prefix="$exec_prefix"
fi
acl_save_prefix="$prefix"
prefix="$acl_final_prefix"
eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
prefix="$acl_save_prefix"
])
dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
dnl variables prefix and exec_prefix bound to the values they will have
dnl at the end of the configure script.
AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
[
acl_save_prefix="$prefix"
prefix="$acl_final_prefix"
acl_save_exec_prefix="$exec_prefix"
exec_prefix="$acl_final_exec_prefix"
$1
exec_prefix="$acl_save_exec_prefix"
prefix="$acl_save_prefix"
])
dnl AC_LIB_PREPARE_MULTILIB creates
dnl - a variable acl_libdirstem, containing the basename of the libdir, either
dnl "lib" or "lib64" or "lib/64",
dnl - a variable acl_libdirstem2, as a secondary possible value for
dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or
dnl "lib/amd64".
AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
[
dnl There is no formal standard regarding lib and lib64.
dnl On glibc systems, the current practice is that on a system supporting
dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine
dnl the compiler's default mode by looking at the compiler's library search
dnl path. If at least one of its elements ends in /lib64 or points to a
dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI.
dnl Otherwise we use the default, namely "lib".
dnl On Solaris systems, the current practice is that on a system supporting
dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or
dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib.
AC_REQUIRE([AC_CANONICAL_HOST])
acl_libdirstem=lib
acl_libdirstem2=
case "$host_os" in
solaris*)
dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment
dnl <http://docs.sun.com/app/docs/doc/816-5138/dev-env?l=en&a=view>.
dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link."
dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the
dnl symlink is missing, so we set acl_libdirstem2 too.
AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit],
[AC_EGREP_CPP([sixtyfour bits], [
#ifdef _LP64
sixtyfour bits
#endif
], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no])
])
if test $gl_cv_solaris_64bit = yes; then
acl_libdirstem=lib/64
case "$host_cpu" in
sparc*) acl_libdirstem2=lib/sparcv9 ;;
i*86 | x86_64) acl_libdirstem2=lib/amd64 ;;
esac
fi
;;
*)
searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
if test -n "$searchpath"; then
acl_save_IFS="${IFS= }"; IFS=":"
for searchdir in $searchpath; do
if test -d "$searchdir"; then
case "$searchdir" in
*/lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
*) searchdir=`cd "$searchdir" && pwd`
case "$searchdir" in
*/lib64 ) acl_libdirstem=lib64 ;;
esac ;;
esac
fi
done
IFS="$acl_save_IFS"
fi
;;
esac
test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem"
])

View File

@ -0,0 +1,142 @@
PAM_U2F(8)
==========
:doctype: manpage
:man source: pam-u2f
:man manual: PAM U2F Module Manual
== NAME
pam_u2f - Module for U2F authentication
== SYNOPSIS
*pam_u2f* [...]
== DESCRIPTION
The module provides U2F authentication against Yubikeys and other compliant authenticators.
== OPTIONS
*debug*::
Enables debug output
*debug_file*::
Filename to write debugging messages to. *If this file is missing, nothing will be logged*. This regular file *has to be created by the user*
or *must exist and be a regular file* for anything getting logged to it. It is not created by pam-u2f on purpose (for security considerations).
This filename may be alternatively set to "stderr" (default), "stdout", or "syslog".
*origin*=_origin_::
Set the origin for the U2F authentication procedure. If no value is specified, the origin "pam://$HOSTNAME" is used.
*appid*=_appid_::
Set the application ID for the U2F authentication procedure. If no value is specified, the same value used for origin is taken ("pam://$HOSTNAME" if also origin is not specified).
*authfile*=_file_::
Set the location of the file that holds the mappings of user names to keyHandles and user keys. The format is username:keyHandle1,public_key1:keyHandle2,public_key2:... the default location of the file is $XDG_CONFIG_HOME/Yubico/u2f_keys. If the environment variable is not set, $HOME/.config/Yubico/u2f_keys is used.
An individual (per user) file may be configured relative to the users' home dirs, i.e. ".ssh/u2f_keys".
*authpending_file*=_file_::
Set the location of the file that is used for touch request notifications. This file will be opened when pam-u2f starts waiting for a user to touch the device, and will be closed when it no longer waits for a touch. Use inotify to listen on these events, or a more high-level tool like yubikey-touch-detector. Default value: /var/run/user/$UID/pam-u2f-authpending. Set an empty value in order to disable this functionality, like so: "authpending_file=".
*nouserok*::
Set to enable authentication attempts to succeed even if the user trying to authenticate is not found inside authfile or if authfile is missing/malformed.
*openasuser*::
Setuid to the authenticating user when opening the authfile. Useful when the user's home is stored on an NFS volume mounted with the root_squash option (which maps root to nobody which will not be able to read the file).
Note that after release 1.0.8 this is done by default when no global authfile or XDG_CONFIG_HOME environment variable has been set.
*alwaysok*::
Set to enable all authentication attempts to succeed (aka presentation mode).
*max_devices*=_n_devices_::
Maximum number of devices allowed per user (default is 24). Devices specified
in the authentication file that exceed this value will be ignored.
*interactive*::
Set to prompt a message and wait before testing the presence of a U2F device. Recommended if your device doesn't have tactile trigger.
*[prompt=your prompt here]*::
Set individual prompt message for interactive mode. Watch the square brackets
around this parameter to get spaces correctly recognized by PAM.
*manual*::
Set to drop to a manual console where challenges are printed on screen and response read from standard input. Useful for debugging and SSH sessions without U2F-support from the SSH client/server. If enabled, interactive mode becomes redundant and has no effect.
*cue*::
Set to prompt a message to remind to touch the device.
*[cue_prompt=your prompt here]*::
Set individual prompt message for the cue option. Watch the square brackets
around this parameter to get spaces correctly recognized by PAM.
*nodetect*::
Skip detecting if a suitable key is inserted before performing a full authentication. See *NOTES* below.
*userpresence*=_int_::
If 1, require user presence during authentication. If 0, do not request user
presence during authentication. Otherwise, fallback to the authenticator's
default behaviour.
*userverification*=_int_::
If 1, require user verification during authentication. If 0, do not request
user verification during authentication. Otherwise, fallback to the
authenticator's default behaviour.
*pinverification*=_int_::
If 1, require PIN verification during authentication. If 0, do not request
PIN verification during authentication. Otherwise, fallback to the
authenticator's default behaviour.
== EXAMPLES
auth sufficient pam_u2f.so debug origin=pam://$HOSTNAME appid=pam://$HOSTNAME
auth required pam_u2f.so origin=http://example.com appid=http://example.com authfile=/etc/yubikey_mappings
== CAVEATS
By default the mapping file inside a home directory will be opened as
the target user, whereas the central file will be opened as "root". If
the "XDG_CONFIG_HOME" variable is set, privileges will not be dropped
unless the "openasuser" configuration setting is set.
Using pam-u2f to secure the login to a computer while
storing the mapping file in an encrypted home directory, will result
in the impossibility of logging into the system. The partition is
decrypted after login and the mapping file can not be accessed.
== NOTES
The "nodetect" option should be used with caution. pam_u2f checks that a
key configured for the user is inserted before performing the full tactile
authentication. This detection is done by sending a "check-only"
authentication request to all inserted tokens to so see if at least one of
them responds affirmatively to one or more of the keyhandles configured for
the user. By doing this, pam_u2f can avoid emitting the "cue" prompt (if
configured), which can cause some confusing UI issues if the cue is emitted
followed by the underlying library immediately failing the tactile
authentication. This option is also useful to avoid an unintended 1-second
delay prior to the tactile authentication caused by versions of libu2f-host
\<= 1.1.5.
If pam_u2f is configured to "cue" and "nodetect", an attacker can determine
that pam_u2f is part of the authentication stack by inserting any random
U2F token and performing an authentication attempt. In this scenario, the
attacker would see the cue message followed by an immediate failure,
whereas with detection enabled, the U2F authentication will fail silently.
Understand that an attacker could choose a U2F token that alerts him or
her in some way to the "check-only" authentication attempt, so this
precaution only pushes the issue back a step.
In summary, the detection feature was added to avoid confusing UI issues
and to prevent leaking information about the authentication stack in very
specific scenario when "cue" is configured. The "nodetect" option was added
to avoid buggy sleep behavior in older versions of libu2f-host and for
hypothetical tokens that do not tolerate the double authentication.
Detection is performed, and likewise "nodetect" honored, regardless of
whether "cue" is also specified.
== BUGS
Report pam-u2f bugs in the issue tracker: https://github.com/Yubico/pam-u2f/issues
== SEE ALSO
*pam*(7)
The pam-u2f home page: https://developers.yubico.com/pam-u2f/
YubiKeys can be obtained from Yubico: http://www.yubico.com/

View File

@ -0,0 +1,60 @@
PAMU2FCFG(1)
============
:doctype: manpage
:man source: pamu2fcfg
:man manual: PAM U2F Configuration Tool
== NAME
pamu2fcfg - Configuration tool for the U2F PAM module.
== SYNOPSIS
*pamu2fcfg* [_OPTION_]...
== DESCRIPTION
Perform a U2F registration procedure using a connected U2F token and output a configuration line that can be used with the U2F PAM module.
== OPTIONS
*-d*, *--debug*::
Print debug information (highly verbose)
*-h*, *--help*::
Print help and exit
*-o*, *--origin*=_STRING_::
Origin URL to use during registration. Defaults to pam://hostname
*-i*, *--appid*=_STRING_::
Application ID to use during registration. Defaults to *origin*
*-r*, *--resident*::
Generate a resident credential. Defaults to off.
*-t*, *--type*=_STRING_::
COSE type to use during registration (ES256 or RS256). Defaults to ES256.
*-N*, *--pin-verification*::
Require PIN verification during authentication. Defaults to off.
*-V*, *--user-verification*::
Require user verification during authentication. Defaults to off.
*--version*:
*Print version and exit*
Group: user (mutually exclusive)
*-u*, *--username*=_STRING_::
The name of the user registering the device. Defaults to the current user name
*-n*, *--nouser*::
Print only registration information (keyHandle and public key). Useful for appending
== BUGS
Report pamu2fcfg bugs in the issue tracker: https://github.com/Yubico/pam-u2f/issues
== SEE ALSO
*pam_u2f*(8), *pam*(7)
The pam-u2f home page: https://developers.yubico.com/pam-u2f/
YubiKeys can be obtained from Yubico: https://www.yubico.com/

472
external/bsd/pam-u2f/dist/pam-u2f.c vendored Normal file
View File

@ -0,0 +1,472 @@
/*
* Copyright (C) 2014-2019 Yubico AB - See COPYING
*/
/* Define which PAM interfaces we provide */
#define PAM_SM_AUTH
/* Include PAM headers */
#include <security/pam_appl.h>
#include <security/pam_modules.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <syslog.h>
#include <pwd.h>
#include <string.h>
#include <errno.h>
#include "util.h"
#include "drop_privs.h"
/* If secure_getenv is not defined, define it here */
#ifndef HAVE_SECURE_GETENV
char *secure_getenv(const char *);
char *secure_getenv(const char *name) {
(void) name;
return NULL;
}
#endif
static void parse_cfg(int flags, int argc, const char **argv, cfg_t *cfg) {
struct stat st;
FILE *file = NULL;
int fd = -1;
int i;
memset(cfg, 0, sizeof(cfg_t));
cfg->debug_file = stderr;
cfg->userpresence = -1;
cfg->userverification = -1;
cfg->pinverification = -1;
for (i = 0; i < argc; i++) {
if (strncmp(argv[i], "max_devices=", 12) == 0)
sscanf(argv[i], "max_devices=%u", &cfg->max_devs);
if (strcmp(argv[i], "manual") == 0)
cfg->manual = 1;
if (strcmp(argv[i], "debug") == 0)
cfg->debug = 1;
if (strcmp(argv[i], "nouserok") == 0)
cfg->nouserok = 1;
if (strcmp(argv[i], "openasuser") == 0)
cfg->openasuser = 1;
if (strcmp(argv[i], "alwaysok") == 0)
cfg->alwaysok = 1;
if (strcmp(argv[i], "interactive") == 0)
cfg->interactive = 1;
if (strcmp(argv[i], "cue") == 0)
cfg->cue = 1;
if (strcmp(argv[i], "nodetect") == 0)
cfg->nodetect = 1;
if (strncmp(argv[i], "userpresence=", 13) == 0)
sscanf(argv[i], "userpresence=%d", &cfg->userpresence);
if (strncmp(argv[i], "userverification=", 17) == 0)
sscanf(argv[i], "userverification=%d", &cfg->userverification);
if (strncmp(argv[i], "pinverification=", 16) == 0)
sscanf(argv[i], "pinverification=%d", &cfg->pinverification);
if (strncmp(argv[i], "authfile=", 9) == 0)
cfg->auth_file = argv[i] + 9;
if (strncmp(argv[i], "authpending_file=", 17) == 0)
cfg->authpending_file = argv[i] + 17;
if (strncmp(argv[i], "origin=", 7) == 0)
cfg->origin = argv[i] + 7;
if (strncmp(argv[i], "appid=", 6) == 0)
cfg->appid = argv[i] + 6;
if (strncmp(argv[i], "prompt=", 7) == 0)
cfg->prompt = argv[i] + 7;
if (strncmp(argv[i], "cue_prompt=", 11) == 0)
cfg->cue_prompt = argv[i] + 11;
if (strncmp(argv[i], "debug_file=", 11) == 0) {
const char *filename = argv[i] + 11;
if (strncmp(filename, "stdout", 6) == 0) {
cfg->debug_file = stdout;
} else if (strncmp(filename, "stderr", 6) == 0) {
cfg->debug_file = stderr;
} else if (strncmp(filename, "syslog", 6) == 0) {
cfg->debug_file = (FILE *) -1;
} else {
fd = open(filename,
O_WRONLY | O_APPEND | O_CLOEXEC | O_NOFOLLOW | O_NOCTTY);
if (fd >= 0 && (fstat(fd, &st) == 0) && S_ISREG(st.st_mode)) {
file = fdopen(fd, "a");
if (file != NULL) {
cfg->debug_file = file;
cfg->is_custom_debug_file = 1;
file = NULL;
fd = -1;
}
}
}
}
}
if (cfg->debug) {
D(cfg->debug_file, "called.");
D(cfg->debug_file, "flags %d argc %d", flags, argc);
for (i = 0; i < argc; i++) {
D(cfg->debug_file, "argv[%d]=%s", i, argv[i]);
}
D(cfg->debug_file, "max_devices=%d", cfg->max_devs);
D(cfg->debug_file, "debug=%d", cfg->debug);
D(cfg->debug_file, "interactive=%d", cfg->interactive);
D(cfg->debug_file, "cue=%d", cfg->cue);
D(cfg->debug_file, "nodetect=%d", cfg->nodetect);
D(cfg->debug_file, "userpresence=%d", cfg->userpresence);
D(cfg->debug_file, "userverification=%d", cfg->userverification);
D(cfg->debug_file, "pinverification=%d", cfg->pinverification);
D(cfg->debug_file, "manual=%d", cfg->manual);
D(cfg->debug_file, "nouserok=%d", cfg->nouserok);
D(cfg->debug_file, "openasuser=%d", cfg->openasuser);
D(cfg->debug_file, "alwaysok=%d", cfg->alwaysok);
D(cfg->debug_file, "authfile=%s",
cfg->auth_file ? cfg->auth_file : "(null)");
D(cfg->debug_file, "authpending_file=%s",
cfg->authpending_file ? cfg->authpending_file : "(null)");
D(cfg->debug_file, "origin=%s", cfg->origin ? cfg->origin : "(null)");
D(cfg->debug_file, "appid=%s", cfg->appid ? cfg->appid : "(null)");
D(cfg->debug_file, "prompt=%s", cfg->prompt ? cfg->prompt : "(null)");
}
if (fd != -1)
close(fd);
if (file != NULL)
fclose(file);
}
#ifdef DBG
#undef DBG
#endif
#define DBG(...) \
if (cfg->debug) { \
D(cfg->debug_file, __VA_ARGS__); \
}
/* PAM entry point for authentication verification */
int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc,
const char **argv) {
struct passwd *pw = NULL, pw_s;
const char *user = NULL;
cfg_t cfg_st;
cfg_t *cfg = &cfg_st;
char buffer[BUFSIZE];
char *buf = NULL;
char *authfile_dir;
size_t authfile_dir_len;
int pgu_ret, gpn_ret;
int retval = PAM_IGNORE;
device_t *devices = NULL;
unsigned n_devices = 0;
int openasuser = 0;
int should_free_origin = 0;
int should_free_appid = 0;
int should_free_auth_file = 0;
int should_free_authpending_file = 0;
PAM_MODUTIL_DEF_PRIVS(privs);
parse_cfg(flags, argc, argv, cfg);
if (!cfg->origin) {
strcpy(buffer, DEFAULT_ORIGIN_PREFIX);
if (gethostname(buffer + strlen(DEFAULT_ORIGIN_PREFIX),
BUFSIZE - strlen(DEFAULT_ORIGIN_PREFIX)) == -1) {
DBG("Unable to get host name");
goto done;
}
DBG("Origin not specified, using \"%s\"", buffer);
cfg->origin = strdup(buffer);
if (!cfg->origin) {
DBG("Unable to allocate memory");
goto done;
} else {
should_free_origin = 1;
}
}
if (!cfg->appid) {
DBG("Appid not specified, using the same value of origin (%s)",
cfg->origin);
cfg->appid = strdup(cfg->origin);
if (!cfg->appid) {
DBG("Unable to allocate memory")
goto done;
} else {
should_free_appid = 1;
}
}
if (cfg->max_devs == 0) {
DBG("Maximum devices number not set. Using default (%d)", MAX_DEVS);
cfg->max_devs = MAX_DEVS;
}
devices = calloc(cfg->max_devs, sizeof(device_t));
if (!devices) {
DBG("Unable to allocate memory");
retval = PAM_IGNORE;
goto done;
}
pgu_ret = pam_get_user(pamh, &user, NULL);
if (pgu_ret != PAM_SUCCESS || user == NULL) {
DBG("Unable to access user %s", user);
retval = PAM_CONV_ERR;
goto done;
}
DBG("Requesting authentication for user %s", user);
gpn_ret = getpwnam_r(user, &pw_s, buffer, sizeof(buffer), &pw);
if (gpn_ret != 0 || pw == NULL || pw->pw_dir == NULL ||
pw->pw_dir[0] != '/') {
DBG("Unable to retrieve credentials for user %s, (%s)", user,
strerror(errno));
retval = PAM_USER_UNKNOWN;
goto done;
}
DBG("Found user %s", user);
DBG("Home directory for %s is %s", user, pw->pw_dir);
if (!cfg->auth_file) {
buf = NULL;
authfile_dir = secure_getenv(DEFAULT_AUTHFILE_DIR_VAR);
if (!authfile_dir) {
DBG("Variable %s is not set. Using default value ($HOME/.config/)",
DEFAULT_AUTHFILE_DIR_VAR);
authfile_dir_len =
strlen(pw->pw_dir) + strlen("/.config") + strlen(DEFAULT_AUTHFILE) + 1;
buf = malloc(sizeof(char) * (authfile_dir_len));
if (!buf) {
DBG("Unable to allocate memory");
retval = PAM_IGNORE;
goto done;
}
/* Opening a file in a users $HOME, need to drop privs for security */
openasuser = geteuid() == 0 ? 1 : 0;
snprintf(buf, authfile_dir_len, "%s/.config%s", pw->pw_dir,
DEFAULT_AUTHFILE);
} else {
DBG("Variable %s set to %s", DEFAULT_AUTHFILE_DIR_VAR, authfile_dir);
authfile_dir_len = strlen(authfile_dir) + strlen(DEFAULT_AUTHFILE) + 1;
buf = malloc(sizeof(char) * (authfile_dir_len));
if (!buf) {
DBG("Unable to allocate memory");
retval = PAM_IGNORE;
goto done;
}
snprintf(buf, authfile_dir_len, "%s%s", authfile_dir, DEFAULT_AUTHFILE);
if (!cfg->openasuser) {
DBG("WARNING: not dropping privileges when reading %s, please "
"consider setting openasuser=1 in the module configuration",
buf);
}
}
DBG("Using authentication file %s", buf);
cfg->auth_file = buf; /* cfg takes ownership */
should_free_auth_file = 1;
buf = NULL;
} else {
if (cfg->auth_file[0] != '/') {
/* Individual authorization mapping by user: auth_file is not
absolute path, so prepend user home dir. */
openasuser = geteuid() == 0 ? 1 : 0;
authfile_dir_len =
strlen(pw->pw_dir) + strlen("/") + strlen(cfg->auth_file) + 1;
buf = malloc(sizeof(char) * (authfile_dir_len));
if (!buf) {
DBG("Unable to allocate memory");
retval = PAM_IGNORE;
goto done;
}
snprintf(buf, authfile_dir_len, "%s/%s", pw->pw_dir, cfg->auth_file);
cfg->auth_file = buf; /* update cfg */
should_free_auth_file = 1;
buf = NULL;
}
DBG("Using authentication file %s", cfg->auth_file);
}
if (!openasuser) {
openasuser = geteuid() == 0 && cfg->openasuser;
}
if (openasuser) {
DBG("Dropping privileges");
if (pam_modutil_drop_priv(pamh, &privs, pw)) {
DBG("Unable to switch user to uid %i", pw->pw_uid);
retval = PAM_IGNORE;
goto done;
}
DBG("Switched to uid %i", pw->pw_uid);
}
retval =
get_devices_from_authfile(cfg->auth_file, user, cfg->max_devs, cfg->debug,
cfg->debug_file, devices, &n_devices);
if (openasuser) {
if (pam_modutil_regain_priv(pamh, &privs)) {
DBG("could not restore privileges");
retval = PAM_IGNORE;
goto done;
}
DBG("Restored privileges");
}
if (retval != 1) {
// for nouserok; make sure errors in get_devices_from_authfile don't
// result in valid devices
n_devices = 0;
}
if (n_devices == 0) {
if (cfg->nouserok) {
DBG("Found no devices but nouserok specified. Skipping authentication");
retval = PAM_SUCCESS;
goto done;
} else if (retval != 1) {
DBG("Unable to get devices from file %s", cfg->auth_file);
retval = PAM_AUTHINFO_UNAVAIL;
goto done;
} else {
DBG("Found no devices. Aborting.");
retval = PAM_AUTHINFO_UNAVAIL;
goto done;
}
}
// Determine the full path for authpending_file in order to emit touch request
// notifications
if (!cfg->authpending_file) {
int actual_size =
snprintf(buffer, BUFSIZE, DEFAULT_AUTHPENDING_FILE_PATH, getuid());
if (actual_size >= 0 && actual_size < BUFSIZE) {
cfg->authpending_file = strdup(buffer);
}
if (!cfg->authpending_file) {
DBG("Unable to allocate memory for the authpending_file, touch request "
"notifications will not be emitted");
} else {
should_free_authpending_file = 1;
}
} else {
if (strlen(cfg->authpending_file) == 0) {
DBG("authpending_file is set to an empty value, touch request "
"notifications will be disabled");
cfg->authpending_file = NULL;
}
}
int authpending_file_descriptor = -1;
if (cfg->authpending_file) {
DBG("Using file '%s' for emitting touch request notifications",
cfg->authpending_file);
// Open (or create) the authpending_file to indicate that we start waiting
// for a touch
authpending_file_descriptor =
open(cfg->authpending_file,
O_RDONLY | O_CREAT | O_CLOEXEC | O_NOFOLLOW | O_NOCTTY, 0664);
if (authpending_file_descriptor < 0) {
DBG("Unable to emit 'authentication started' notification by opening the "
"file '%s', (%s)",
cfg->authpending_file, strerror(errno));
}
}
if (cfg->manual == 0) {
if (cfg->interactive) {
converse(pamh, PAM_PROMPT_ECHO_ON,
cfg->prompt != NULL ? cfg->prompt : DEFAULT_PROMPT);
}
retval = do_authentication(cfg, devices, n_devices, pamh);
} else {
retval = do_manual_authentication(cfg, devices, n_devices, pamh);
}
// Close the authpending_file to indicate that we stop waiting for a touch
if (authpending_file_descriptor >= 0) {
if (close(authpending_file_descriptor) < 0) {
DBG("Unable to emit 'authentication stopped' notification by closing the "
"file '%s', (%s)",
cfg->authpending_file, strerror(errno));
}
}
if (retval != 1) {
DBG("do_authentication returned %d", retval);
retval = PAM_AUTH_ERR;
goto done;
}
retval = PAM_SUCCESS;
done:
free_devices(devices, n_devices);
if (buf) {
free(buf);
buf = NULL;
}
if (should_free_origin) {
free((char *) cfg->origin);
cfg->origin = NULL;
}
if (should_free_appid) {
free((char *) cfg->appid);
cfg->appid = NULL;
}
if (should_free_auth_file) {
free((char *) cfg->auth_file);
cfg->auth_file = NULL;
}
if (should_free_authpending_file) {
free((char *) cfg->authpending_file);
cfg->authpending_file = NULL;
}
if (cfg->alwaysok && retval != PAM_SUCCESS) {
DBG("alwaysok needed (otherwise return with %d)", retval);
retval = PAM_SUCCESS;
}
DBG("done. [%s]", pam_strerror(pamh, retval));
if (cfg->is_custom_debug_file) {
fclose(cfg->debug_file);
}
return retval;
}
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc,
const char **argv) {
(void) pamh;
(void) flags;
(void) argc;
(void) argv;
return PAM_SUCCESS;
}

View File

@ -0,0 +1,31 @@
# Copyright (C) 2014-2018 Yubico AB - See COPYING
AM_CFLAGS = $(WARN_CFLAGS)
AM_CPPFLAGS=-I$(srcdir)/.. -I$(builddir)/.. $(LIBFIDO2_CFLAGS)
bin_PROGRAMS = pamu2fcfg
pamu2fcfg_SOURCES = pamu2fcfg.c
pamu2fcfg_SOURCES += cmdline.ggo cmdline.c cmdline.h
pamu2fcfg_SOURCES += readpassphrase.c readpassphrase.h
pamu2fcfg_SOURCES += ../util.c ../b64.c ../explicit_bzero.c
pamu2fcfg_LDADD = $(LIBFIDO2_LIBS) $(LIBCRYPTO_LIBS)
cmdline.c cmdline.h: cmdline.ggo Makefile.am
gengetopt --no-handle-help --input $^
BUILT_SOURCES = cmdline.c cmdline.h
MAINTAINERCLEANFILES = $(BUILT_SOURCES)
if ENABLE_MAN
dist_man1_MANS = $(top_builddir)/man/pamu2fcfg.1
DISTCLEANFILES = $(dist_man1_MANS)
MANSOURCES = $(top_builddir)/man/pamu2fcfg.1.txt
EXTRA_DIST = $(MANSOURCES)
SUFFIXES = .1.txt .1
.1.txt.1:
$(A2X) --format=manpage -L -a revdate="Version $(VERSION)" $<
endif

View File

@ -0,0 +1,42 @@
/* $OpenBSD: readpassphrase.h,v 1.5 2003/06/17 21:56:23 millert Exp $ */
/*
* Copyright (c) 2000, 2002 Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/* OPENBSD ORIGINAL: include/readpassphrase.h */
#ifndef _READPASSPHRASE_H_
#define _READPASSPHRASE_H_
#ifndef HAVE_READPASSPHRASE
#define RPP_ECHO_OFF 0x00 /* Turn off echo (default). */
#define RPP_ECHO_ON 0x01 /* Leave echo on. */
#define RPP_REQUIRE_TTY 0x02 /* Fail if there is no tty. */
#define RPP_FORCELOWER 0x04 /* Force input to lower case. */
#define RPP_FORCEUPPER 0x08 /* Force input to upper case. */
#define RPP_SEVENBIT 0x10 /* Strip the high bit from input. */
#define RPP_STDIN 0x20 /* Read from stdin, not /dev/tty */
char * readpassphrase(const char *, char *, size_t, int);
#endif /* HAVE_READPASSPHRASE */
#endif /* !_READPASSPHRASE_H_ */

View File

@ -0,0 +1,18 @@
# Copyright (C) 2014-2018 Yubico AB - See COPYING
#
purpose "Perform a U2F registration operation and print a configuration line that can be used with the pam_u2f module."
defgroup "user"
option "origin" o "Origin URL to use during registration. Defaults to pam://hostname" string optional
option "appid" i "Application ID to use during registration. Defaults to pam://hostname" string optional
option "type" t "COSE type to use during registration (ES256 or RS256). Defaults to ES256." string optional
option "resident" r "Generate a resident credential" flag off
option "no-user-presence" P "Allow the credential to be used without ensuring the user's presence" flag off
option "pin-verification" N "Require PIN verification during authentication" flag off
option "user-verification" V "Require user verification during authentication" flag off
option "debug" d "Print debug information (highly verbose)" flag off
option "verbose" v "Print information about chosen origin and appid" flag off
groupoption "username" u "The name of the user registering the device. Defaults to the current user name" string group="user"
groupoption "nouser" n "Print only registration information (keyHandle and public key). Useful for appending" group="user"

View File

@ -0,0 +1,347 @@
/*
* Copyright (C) 2014-2018 Yubico AB - See COPYING
*/
#define BUFSIZE 1024
#define PAM_PREFIX "pam://"
#define TIMEOUT 15
#define FREQUENCY 1
#include <fido.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/types.h>
#include <pwd.h>
#include "b64.h"
#include "cmdline.h"
#include "util.h"
#ifndef HAVE_READPASSPHRASE
#include "_readpassphrase.h"
#else
#include <readpassphrase.h>
#endif
int main(int argc, char *argv[]) {
int exit_code = EXIT_FAILURE;
struct gengetopt_args_info args_info;
char buf[BUFSIZE];
char prompt[BUFSIZE];
char pin[BUFSIZE];
char *p;
char *response;
fido_cred_t *cred = NULL;
fido_dev_info_t *devlist = NULL;
fido_dev_t *dev = NULL;
const fido_dev_info_t *di = NULL;
size_t ndevs;
int cose_type;
int resident_key;
int user_presence;
int user_verification;
int pin_verification;
int r;
int n;
char *origin = NULL;
char *appid = NULL;
char *user = NULL;
char *b64_kh;
char *b64_pk;
struct passwd *passwd;
const unsigned char *kh = NULL;
size_t kh_len;
const unsigned char *pk = NULL;
size_t pk_len;
unsigned char userid[32];
unsigned char challenge[32];
unsigned i;
unsigned max_index = 0;
if (cmdline_parser(argc, argv, &args_info) != 0)
exit(EXIT_FAILURE);
if (args_info.help_given) {
cmdline_parser_print_help();
printf("\nReport bugs at <https://github.com/Yubico/pam-u2f>.\n");
exit(EXIT_SUCCESS);
}
fido_init(args_info.debug_flag ? FIDO_DEBUG : 0);
cred = fido_cred_new();
if (!cred) {
fprintf(stderr, "fido_cred_new failed\n");
exit(EXIT_FAILURE);
}
if (!random_bytes(challenge, sizeof(challenge))) {
fprintf(stderr, "random_bytes failed\n");
exit(EXIT_FAILURE);
}
if (args_info.type_given) {
if (!strcasecmp(args_info.type_arg, "es256"))
cose_type = COSE_ES256;
else if (!strcasecmp(args_info.type_arg, "rs256"))
cose_type = COSE_RS256;
else {
fprintf(stderr, "Unknown COSE type '%s'.\n", args_info.type_arg);
exit(EXIT_FAILURE);
}
} else
cose_type = COSE_ES256;
r = fido_cred_set_type(cred, cose_type);
if (r != FIDO_OK) {
fprintf(stderr, "error: fido_cred_set_type (%d): %s\n", r, fido_strerr(r));
exit(EXIT_FAILURE);
}
r = fido_cred_set_clientdata_hash(cred, challenge, sizeof(challenge));
if (r != FIDO_OK) {
fprintf(stderr, "error: fido_cred_set_clientdata_hash (%d): %s\n", r,
fido_strerr(r));
exit(EXIT_FAILURE);
}
if (args_info.origin_given)
origin = args_info.origin_arg;
else {
if (!strcpy(buf, PAM_PREFIX)) {
fprintf(stderr, "strcpy failed\n");
exit(EXIT_FAILURE);
}
if (gethostname(buf + strlen(PAM_PREFIX), BUFSIZE - strlen(PAM_PREFIX)) ==
-1) {
perror("gethostname");
exit(EXIT_FAILURE);
}
origin = buf;
}
if (args_info.verbose_given)
fprintf(stderr, "Setting origin to %s\n", origin);
if (args_info.appid_given)
appid = args_info.appid_arg;
else {
appid = origin;
}
if (args_info.verbose_given)
fprintf(stderr, "Setting appid to %s\n", appid);
r = fido_cred_set_rp(cred, origin, appid);
if (r != FIDO_OK) {
fprintf(stderr, "error: fido_cred_set_rp (%d) %s\n", r, fido_strerr(r));
exit(EXIT_FAILURE);
}
if (args_info.username_given)
user = args_info.username_arg;
else {
passwd = getpwuid(getuid());
if (passwd == NULL) {
perror("getpwuid");
exit(EXIT_FAILURE);
}
user = passwd->pw_name;
}
if (!random_bytes(userid, sizeof(userid))) {
fprintf(stderr, "random_bytes failed\n");
exit(EXIT_FAILURE);
}
if (args_info.verbose_given) {
fprintf(stderr, "Setting user to %s\n", user);
fprintf(stderr, "Setting user id to ");
for (size_t i = 0; i < sizeof(userid); i++)
fprintf(stderr, "%02x", userid[i]);
fprintf(stderr, "\n");
}
r = fido_cred_set_user(cred, userid, sizeof(userid), user, NULL, NULL);
if (r != FIDO_OK) {
fprintf(stderr, "error: fido_cred_set_user (%d) %s\n", r, fido_strerr(r));
exit(EXIT_FAILURE);
}
if (args_info.resident_given)
resident_key = 1;
else
resident_key = 0;
if (args_info.no_user_presence_given)
user_presence = 0;
else
user_presence = 1;
if (args_info.user_verification_given)
user_verification = 1;
else
user_verification = 0;
if (args_info.pin_verification_given)
pin_verification = 1;
else
pin_verification = 0;
r = fido_cred_set_rk(cred, resident_key);
if (r != FIDO_OK) {
fprintf(stderr, "error: fido_cred_set_rk (%d) %s\n", r, fido_strerr(r));
exit(EXIT_FAILURE);
}
r = fido_cred_set_uv(cred, false);
if (r != FIDO_OK) {
fprintf(stderr, "error: fido_cred_set_uv (%d) %s\n", r, fido_strerr(r));
exit(EXIT_FAILURE);
}
devlist = fido_dev_info_new(64);
if (!devlist) {
fprintf(stderr, "error: fido_dev_info_new failed\n");
exit(EXIT_FAILURE);
}
r = fido_dev_info_manifest(devlist, 64, &ndevs);
if (r != FIDO_OK) {
fprintf(stderr, "Unable to discover device(s), %s (%d)\n", fido_strerr(r),
r);
exit(EXIT_FAILURE);
}
if (ndevs == 0) {
for (i = 0; i < TIMEOUT; i += FREQUENCY) {
fprintf(stderr,
"\rNo U2F device available, please insert one now, you "
"have %2d seconds",
TIMEOUT - i);
fflush(stderr);
sleep(FREQUENCY);
r = fido_dev_info_manifest(devlist, 64, &ndevs);
if (r != FIDO_OK) {
fprintf(stderr, "\nUnable to discover device(s), %s (%d)",
fido_strerr(r), r);
exit(EXIT_FAILURE);
}
if (ndevs != 0) {
fprintf(stderr, "\nDevice found!\n");
break;
}
}
}
if (ndevs == 0) {
fprintf(stderr, "\rNo device found. Aborting. "
" \n");
exit(EXIT_FAILURE);
}
/* XXX loop over every device? */
dev = fido_dev_new();
if (!dev) {
fprintf(stderr, "fido_dev_new failed\n");
exit(EXIT_FAILURE);
}
di = fido_dev_info_ptr(devlist, 0);
if (!di) {
fprintf(stderr, "error: fido_dev_info_ptr returned NULL\n");
exit(EXIT_FAILURE);
}
r = fido_dev_open(dev, fido_dev_info_path(di));
if (r != FIDO_OK) {
fprintf(stderr, "error: fido_dev_open (%d) %s\n", r, fido_strerr(r));
exit(EXIT_FAILURE);
}
r = fido_dev_make_cred(dev, cred, NULL);
if (r == FIDO_ERR_PIN_REQUIRED) {
n = snprintf(prompt, sizeof(prompt),
"Enter PIN for %s: ", fido_dev_info_path(di));
if (n < 0 || (size_t) n >= sizeof(prompt)) {
fprintf(stderr, "error: snprintf prompt");
exit(EXIT_FAILURE);
}
if (!readpassphrase(prompt, pin, sizeof(pin), RPP_ECHO_OFF)) {
fprintf(stderr, "error: failed to read pin");
exit(EXIT_FAILURE);
}
r = fido_dev_make_cred(dev, cred, pin);
}
explicit_bzero(pin, sizeof(pin));
if (r != FIDO_OK) {
fprintf(stderr, "error: fido_dev_make_cred (%d) %s\n", r, fido_strerr(r));
exit(EXIT_FAILURE);
}
r = fido_cred_verify(cred);
if (r != FIDO_OK) {
fprintf(stderr, "error: fido_cred_verify (%d) %s\n", r, fido_strerr(r));
exit(EXIT_FAILURE);
}
kh = fido_cred_id_ptr(cred);
if (!kh) {
fprintf(stderr, "error: fido_cred_id_ptr returned NULL\n");
exit(EXIT_FAILURE);
}
kh_len = fido_cred_id_len(cred);
if (kh_len == 0) {
fprintf(stderr, "error: fido_cred_id_len returned 0\n");
exit(EXIT_FAILURE);
}
pk = (const unsigned char *) fido_cred_pubkey_ptr(cred);
if (!pk) {
fprintf(stderr, "error: fido_cred_pubkey_ptr returned NULL\n");
exit(EXIT_FAILURE);
}
pk_len = fido_cred_pubkey_len(cred);
if (pk_len == 0) {
fprintf(stderr, "error: fido_cred_pubkey_len returned 0\n");
exit(EXIT_FAILURE);
}
if (!b64_encode(kh, kh_len, &b64_kh)) {
fprintf(stderr, "error: failed to encode key handle\n");
exit(EXIT_FAILURE);
}
if (!b64_encode(pk, pk_len, &b64_pk)) {
fprintf(stderr, "error: failed to encode public key\n");
exit(EXIT_FAILURE);
}
if (!args_info.nouser_given)
printf("%s", user);
printf(":%s,%s,%s,%s%s%s", resident_key ? "*" : b64_kh, b64_pk,
cose_type == COSE_ES256 ? "es256" : "rs256",
user_presence ? "+presence" : "",
user_verification ? "+verification" : "",
pin_verification ? "+pin" : "");
exit_code = EXIT_SUCCESS;
fido_dev_info_free(&devlist, ndevs);
fido_cred_free(&cred);
fido_dev_free(&dev);
free(b64_kh);
free(b64_pk);
exit(exit_code);
}

View File

@ -0,0 +1,214 @@
/* $OpenBSD: readpassphrase.c,v 1.26 2016/10/18 12:47:18 millert Exp $ */
/*
* Copyright (c) 2000-2002, 2007, 2010
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Sponsored in part by the Defense Advanced Research Projects
* Agency (DARPA) and Air Force Research Laboratory, Air Force
* Materiel Command, USAF, under agreement number F39502-99-1-0512.
*/
/* OPENBSD ORIGINAL: lib/libc/gen/readpassphrase.c */
#ifndef HAVE_READPASSPHRASE
#include <termios.h>
#include <signal.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <paths.h>
#include "_readpassphrase.h"
#ifndef _PATH_TTY
# define _PATH_TTY "/dev/tty"
#endif
#ifndef TCSASOFT
/* If we don't have TCSASOFT define it so that ORing it it below is a no-op. */
# define TCSASOFT 0
#endif
/* SunOS 4.x which lacks _POSIX_VDISABLE, but has VDISABLE */
#if !defined(_POSIX_VDISABLE) && defined(VDISABLE)
# define _POSIX_VDISABLE VDISABLE
#endif
static volatile sig_atomic_t signo[_NSIG];
static void handler(int);
char *
readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
{
ssize_t nr;
int input, output, save_errno, i, need_restart;
char ch, *p, *end;
struct termios term, oterm;
struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
struct sigaction savetstp, savettin, savettou, savepipe;
/* I suppose we could alloc on demand in this case (XXX). */
if (bufsiz == 0) {
errno = EINVAL;
return(NULL);
}
restart:
for (i = 0; i < _NSIG; i++)
signo[i] = 0;
need_restart = 0;
/*
* Read and write to /dev/tty if available. If not, read from
* stdin and write to stderr unless a tty is required.
*/
if ((flags & RPP_STDIN) ||
(input = output = open(_PATH_TTY, O_RDWR)) == -1) {
if (flags & RPP_REQUIRE_TTY) {
errno = ENOTTY;
return(NULL);
}
input = STDIN_FILENO;
output = STDERR_FILENO;
}
/*
* Turn off echo if possible.
* If we are using a tty but are not the foreground pgrp this will
* generate SIGTTOU, so do it *before* installing the signal handlers.
*/
if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
memcpy(&term, &oterm, sizeof(term));
if (!(flags & RPP_ECHO_ON))
term.c_lflag &= ~(ECHO | ECHONL);
#ifdef VSTATUS
if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
term.c_cc[VSTATUS] = _POSIX_VDISABLE;
#endif
(void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
} else {
memset(&term, 0, sizeof(term));
term.c_lflag |= ECHO;
memset(&oterm, 0, sizeof(oterm));
oterm.c_lflag |= ECHO;
}
/*
* Catch signals that would otherwise cause the user to end
* up with echo turned off in the shell. Don't worry about
* things like SIGXCPU and SIGVTALRM for now.
*/
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0; /* don't restart system calls */
sa.sa_handler = handler;
(void)sigaction(SIGALRM, &sa, &savealrm);
(void)sigaction(SIGHUP, &sa, &savehup);
(void)sigaction(SIGINT, &sa, &saveint);
(void)sigaction(SIGPIPE, &sa, &savepipe);
(void)sigaction(SIGQUIT, &sa, &savequit);
(void)sigaction(SIGTERM, &sa, &saveterm);
(void)sigaction(SIGTSTP, &sa, &savetstp);
(void)sigaction(SIGTTIN, &sa, &savettin);
(void)sigaction(SIGTTOU, &sa, &savettou);
if (!(flags & RPP_STDIN))
(void)write(output, prompt, strlen(prompt));
end = buf + bufsiz - 1;
p = buf;
while ((nr = read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
if (p < end) {
if ((flags & RPP_SEVENBIT))
ch &= 0x7f;
if (isalpha((unsigned char)ch)) {
if ((flags & RPP_FORCELOWER))
ch = (char)tolower((unsigned char)ch);
if ((flags & RPP_FORCEUPPER))
ch = (char)toupper((unsigned char)ch);
}
*p++ = ch;
}
}
*p = '\0';
save_errno = errno;
if (!(term.c_lflag & ECHO))
(void)write(output, "\n", 1);
/* Restore old terminal settings and signals. */
if (memcmp(&term, &oterm, sizeof(term)) != 0) {
const int sigttou = signo[SIGTTOU];
/* Ignore SIGTTOU generated when we are not the fg pgrp. */
while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 &&
errno == EINTR && !signo[SIGTTOU])
continue;
signo[SIGTTOU] = sigttou;
}
(void)sigaction(SIGALRM, &savealrm, NULL);
(void)sigaction(SIGHUP, &savehup, NULL);
(void)sigaction(SIGINT, &saveint, NULL);
(void)sigaction(SIGQUIT, &savequit, NULL);
(void)sigaction(SIGPIPE, &savepipe, NULL);
(void)sigaction(SIGTERM, &saveterm, NULL);
(void)sigaction(SIGTSTP, &savetstp, NULL);
(void)sigaction(SIGTTIN, &savettin, NULL);
(void)sigaction(SIGTTOU, &savettou, NULL);
if (input != STDIN_FILENO)
(void)close(input);
/*
* If we were interrupted by a signal, resend it to ourselves
* now that we have restored the signal handlers.
*/
for (i = 0; i < _NSIG; i++) {
if (signo[i]) {
kill(getpid(), i);
switch (i) {
case SIGTSTP:
case SIGTTIN:
case SIGTTOU:
need_restart = 1;
}
}
}
if (need_restart)
goto restart;
if (save_errno)
errno = save_errno;
return(nr == -1 ? NULL : buf);
}
#if 0
char *
getpass(const char *prompt)
{
static char buf[_PASSWORD_LEN + 1];
return(readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF));
}
#endif
static void handler(int s)
{
signo[s] = 1;
}
#endif /* HAVE_READPASSPHRASE */

View File

@ -0,0 +1,12 @@
# Copyright (C) 2014-2018 Yubico AB - See COPYING
#
AM_CFLAGS = $(WARN_CFLAGS)
AM_CPPFLAGS=-I$(srcdir)/.. -I$(builddir)/..
AM_LDFLAGS = -no-install
LDADD = $(top_builddir)/pam_u2f.la
check_PROGRAMS = basic
TESTS = $(check_PROGRAMS)

30
external/bsd/pam-u2f/dist/tests/basic.c vendored Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2014-2018 Yubico AB - See COPYING
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
/* These #defines must be present according to PAM documentation. */
#define PAM_SM_AUTH
#ifdef HAVE_SECURITY_PAM_APPL_H
#include <security/pam_appl.h>
#endif
#ifdef HAVE_SECURITY_PAM_MODULES_H
#include <security/pam_modules.h>
#endif
int
main (int argc, const char **argv)
{
pam_handle_t *pamh = NULL;
int rc;
rc = pam_sm_authenticate (pamh, 0, 1, argv);
printf ("rc %d\n", rc);
return 0;
}

View File

@ -0,0 +1,15 @@
FROM ubuntu:bionic
COPY . /pam-u2f
WORKDIR /pam-u2f
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get -qq update
RUN apt-get -qq upgrade
RUN apt-get install -qq software-properties-common
RUN add-apt-repository ppa:yubico/stable
RUN apt-get -qq update
RUN apt-get install -qq libudev-dev libssl-dev libfido2-dev
RUN apt-get install -qq build-essential autoconf automake libtool pkg-config
RUN apt-get install -qq gengetopt libpam-dev pamtester
RUN autoreconf -i .
RUN ./configure --disable-man
RUN make clean all install

View File

@ -0,0 +1,18 @@
pam-u2f can be tested as follows:
1. Build a Docker image containing everything needed to run pam-u2f.
This can be achieved through the command:
$ docker build -t pam-u2f-test -f tests/bionic/Dockerfile .
2. Connect a YubiKey to the host OS and take note of the path of the
device's U2F endpoint (e.g. /dev/hidraw6).
3. Execute tests/bionic/run.sh in a container, exposing the YubiKey
to the guest OS. This can be done through the command:
$ docker run -it --rm=true --device=/dev/hidraw6 \
pam-u2f-test /pam-u2f/tests/bionic/run.sh
To test U2F devices, pass -e U2F_TOKEN=1 to docker-run. To test
FIDO2 devices configured with a PIN, pass -e FIDO2_PIN=1 to
docker-run.

63
external/bsd/pam-u2f/dist/tests/bionic/run.sh vendored Executable file
View File

@ -0,0 +1,63 @@
#!/bin/sh -ex
mkdir -p ~/.config/Yubico
create_keys() {
pamu2fcfg -t es256 -N > /tmp/es256
[ "${U2F_TOKEN}" != "" ] && return
pamu2fcfg -t es256 -N -r -o originA > /tmp/es256.r
pamu2fcfg -t rs256 -N -r -o originB > /tmp/rs256.r
}
run_tests() {
[ "${U2F_TOKEN}" != "" ] && return
echo "auth sufficient pam_u2f.so" > /etc/pam.d/dummy
cp /tmp/es256 ~/.config/Yubico/u2f_keys
pamtester dummy root authenticate
echo "auth sufficient pam_u2f.so origin=originA" > /etc/pam.d/dummy
cp /tmp/es256.r ~/.config/Yubico/u2f_keys
pamtester dummy root authenticate
echo "auth sufficient pam_u2f.so origin=originB" > /etc/pam.d/dummy
cp /tmp/rs256.r ~/.config/Yubico/u2f_keys
pamtester dummy root authenticate
}
run_user_presence_tests() {
echo "auth sufficient pam_u2f.so" > /etc/pam.d/dummy
cat /tmp/es256 | sed 's/-$/p/' > ~/.config/Yubico/u2f_keys
pamtester dummy root authenticate
[ "${U2F_TOKEN}" != "" ] && return
echo "auth sufficient pam_u2f.so origin=originA" > /etc/pam.d/dummy
cat /tmp/es256.r | sed 's/-$/p/' > ~/.config/Yubico/u2f_keys
pamtester dummy root authenticate
echo "auth sufficient pam_u2f.so origin=originB" > /etc/pam.d/dummy
cat /tmp/rs256.r | sed 's/-$/p/' > ~/.config/Yubico/u2f_keys
pamtester dummy root authenticate
}
run_user_verification_tests() {
[ "${U2F_TOKEN}" != "" ] && return
[ "${FIDO2_PIN}" = "" ] && return
echo "auth sufficient pam_u2f.so" > /etc/pam.d/dummy
cat /tmp/es256 | sed 's/-$/v/' > ~/.config/Yubico/u2f_keys
pamtester dummy root authenticate
echo "auth sufficient pam_u2f.so origin=originA" > /etc/pam.d/dummy
cat /tmp/es256.r | sed 's/-$/v/' > ~/.config/Yubico/u2f_keys
pamtester dummy root authenticate
echo "auth sufficient pam_u2f.so origin=originB" > /etc/pam.d/dummy
cat /tmp/rs256.r | sed 's/-$/v/' > ~/.config/Yubico/u2f_keys
pamtester dummy root authenticate
}
create_keys
run_tests
run_user_presence_tests
run_user_verification_tests

1202
external/bsd/pam-u2f/dist/util.c vendored Normal file

File diff suppressed because it is too large Load Diff

80
external/bsd/pam-u2f/dist/util.h vendored Normal file
View File

@ -0,0 +1,80 @@
/*
* Copyright (C) 2014-2019 Yubico AB - See COPYING
*/
#ifndef UTIL_H
#define UTIL_H
#include <stdio.h>
#include <security/pam_appl.h>
#define BUFSIZE 1024
#define MAX_DEVS 24
#define PK_LEN 130 // Public key
#define KH_LEN 86 // Key handle
#define RD_LEN 40 // Rounding
#define DEVSIZE (((PK_LEN) + (KH_LEN) + (RD_LEN)))
#define DEFAULT_AUTHFILE_DIR_VAR "XDG_CONFIG_HOME"
#define DEFAULT_AUTHFILE "/Yubico/u2f_keys"
#define DEFAULT_AUTHPENDING_FILE_PATH "/var/run/user/%d/pam-u2f-authpending"
#define DEFAULT_PROMPT "Insert your U2F device, then press ENTER."
#define DEFAULT_CUE "Please touch the device."
#define DEFAULT_ORIGIN_PREFIX "pam://"
#define DEBUG_STR "debug(pam_u2f): %s:%d (%s): "
#if defined(DEBUG_PAM)
#define D(file, ...) _debug(file, __FILE__, __LINE__, __func__, __VA_ARGS__)
#else
#define D(file, ...)
#endif /* DEBUG_PAM */
typedef struct {
unsigned max_devs;
const char *client_key;
int manual;
int debug;
int nouserok;
int openasuser;
int alwaysok;
int interactive;
int cue;
int nodetect;
int userpresence;
int userverification;
int pinverification;
const char *auth_file;
const char *authpending_file;
const char *origin;
const char *appid;
const char *prompt;
const char *cue_prompt;
FILE *debug_file;
int is_custom_debug_file;
} cfg_t;
typedef struct {
char *publicKey;
char *keyHandle;
char *coseType;
char *attributes;
int old_format;
} device_t;
int get_devices_from_authfile(const char *authfile, const char *username,
unsigned max_devs, int verbose, FILE *debug_file,
device_t *devices, unsigned *n_devs);
void free_devices(device_t *devices, const unsigned n_devs);
int do_authentication(const cfg_t *cfg, const device_t *devices,
const unsigned n_devs, pam_handle_t *pamh);
int do_manual_authentication(const cfg_t *cfg, const device_t *devices,
const unsigned n_devs, pam_handle_t *pamh);
char *converse(pam_handle_t *pamh, int echocode, const char *prompt);
void _debug(FILE *, const char *, int, const char *, const char *, ...);
int random_bytes(void *, size_t);
#if !defined(HAVE_EXPLICIT_BZERO)
void explicit_bzero(void *, size_t);
#endif
#endif /* UTIL_H */