mirror of
https://github.com/Yubico/yubico-pam.git
synced 2025-03-16 03:29:17 +01:00
Add ykpamcfg - C/R setup command line utility.
This commit is contained in:
parent
b20c0ed678
commit
839b33a0a1
11
Makefile.am
11
Makefile.am
@ -40,6 +40,17 @@ pam_yubico_la_CPPFLAGS = @YKPERS_CFLAGS@
|
|||||||
|
|
||||||
DEFS = -DDEBUG_PAM -DPAM_DEBUG @DEFS@
|
DEFS = -DDEBUG_PAM -DPAM_DEBUG @DEFS@
|
||||||
|
|
||||||
|
# The command line tools.
|
||||||
|
|
||||||
|
bin_PROGRAMS = ykpamcfg
|
||||||
|
|
||||||
|
ykpamcfg_SOURCES = ykpamcfg.c util.c
|
||||||
|
ykpamcfg_LDADD = @LTLIBYKCLIENT@ @YKPERS_LIBS@
|
||||||
|
ykpamcfg_CPPFLAGS = @YKPERS_CFLAGS@
|
||||||
|
|
||||||
|
dist_man1_MANS = ykpamcfg.1
|
||||||
|
|
||||||
|
|
||||||
# Self tests.
|
# Self tests.
|
||||||
|
|
||||||
AM_LDFLAGS = -no-install
|
AM_LDFLAGS = -no-install
|
||||||
|
113
ykpamcfg.1
Normal file
113
ykpamcfg.1
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
.\" Copyright (c) 2011 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.
|
||||||
|
.\"
|
||||||
|
.\" The following commands are required for all man pages.
|
||||||
|
.de URL
|
||||||
|
\\$2 \(laURL: \\$1 \(ra\\$3
|
||||||
|
..
|
||||||
|
.if \n[.g] .mso www.tmac
|
||||||
|
.TH ykpamcfg "1" "March 2011" "yubikey-personalization"
|
||||||
|
.SH NAME
|
||||||
|
ykpamcfg - Manage user settings for the Yubico PAM module.
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ykpamcfg
|
||||||
|
[\fI-1\fR | \fI-2\fR] [\fI-A\fR] [\fI-v\fR] [\fI-h\fR]
|
||||||
|
.\".SH DESCRIPTION
|
||||||
|
.\" Add any additional description here
|
||||||
|
.SH OPTIONS
|
||||||
|
.PP
|
||||||
|
.TP
|
||||||
|
\fB\-1\fR
|
||||||
|
use slot 1. This is the default.
|
||||||
|
.TP
|
||||||
|
\fB\-2\fR
|
||||||
|
use slot 2.
|
||||||
|
.TP
|
||||||
|
\fB\-A \fIaction\fR
|
||||||
|
choose action to perform. See ACTIONS below.
|
||||||
|
.TP
|
||||||
|
\fB\-v\fR
|
||||||
|
enable verbose mode.
|
||||||
|
|
||||||
|
.SH ACTIONS
|
||||||
|
.TP
|
||||||
|
\fBadd_hmac_chalresp\fR
|
||||||
|
The PAM module can utilize the HMAC-SHA1 Challenge-Response mode found in YubiKeys
|
||||||
|
starting with version 2.2 for \fBoffline authentication\fR. This action creates the initial state
|
||||||
|
information with the C/R to be issued at the next logon.
|
||||||
|
|
||||||
|
The utility currently outputs the state information to a file in the current user's
|
||||||
|
home directory (\fI~/.yubico/challenge-123456\fR for a YubiKey with serial number API readout
|
||||||
|
enabled, and \fI~/.yubico/challenge\fR for one without).
|
||||||
|
|
||||||
|
The PAM module supports a system wide directory for these state files (in case the user's
|
||||||
|
home directories are encrypted), but in a system wide directory, the 'challenge' part should
|
||||||
|
be replaced with the username. Example : \fI/var/yubico/challenges/alice-123456\fR.
|
||||||
|
|
||||||
|
To use the system-wide mode, you currently have to move the generated state files manually and
|
||||||
|
configure the PAM module accordingly.
|
||||||
|
|
||||||
|
.SH EXAMPLE
|
||||||
|
First, program a YubiKey for challenge response on Slot 2 :
|
||||||
|
.HP
|
||||||
|
.nf
|
||||||
|
$ \fBykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible\fR
|
||||||
|
...
|
||||||
|
Commit? (y/n) [n]: y
|
||||||
|
$
|
||||||
|
.fi
|
||||||
|
.HP
|
||||||
|
Now, set the current user to require this YubiKey for logon :
|
||||||
|
.HP
|
||||||
|
.nf
|
||||||
|
$ \fBykpamcfg -2 -v\fR
|
||||||
|
...
|
||||||
|
Stored initial challenge and expected response in '/home/alice/.yubico/challenge-123456'.
|
||||||
|
$
|
||||||
|
.fi
|
||||||
|
.HP
|
||||||
|
Then, configure authentication with PAM for example like this (\fImake a backup first\fR) :
|
||||||
|
.HP
|
||||||
|
\fI/etc/pam.d/common-auth\fR (from Ubuntu 10.10) :
|
||||||
|
|
||||||
|
.nf
|
||||||
|
auth required pam_unix.so nullok_secure try_first_pass
|
||||||
|
auth [success=1 new_authtok_reqd=ok ignore=ignore default=die] pam_yubico.so mode=challenge-response
|
||||||
|
auth requisite pam_deny.so
|
||||||
|
auth required pam_permit.so
|
||||||
|
auth optional pam_ecryptfs.so unwrap
|
||||||
|
.fi
|
||||||
|
|
||||||
|
.SH BUGS
|
||||||
|
Report ykpamcfg bugs in
|
||||||
|
.URL "http://code.google.com/p/yubico-pam/issues/list" "the issue tracker"
|
||||||
|
.SH "SEE ALSO"
|
||||||
|
The
|
||||||
|
.URL "http://code.google.com/p/yubico-pam/" "yubico-pam home page"
|
||||||
|
.PP
|
||||||
|
YubiKeys can be obtained from
|
||||||
|
.URL "http://www.yubico.com/" "Yubico" "."
|
244
ykpamcfg.c
Normal file
244
ykpamcfg.c
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Yubico AB.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Author : Fredrik Thulin <fredrik@yubico.com>
|
||||||
|
*
|
||||||
|
* Based on ykchalresp.c from yubikey-personalization.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include <ykpers.h>
|
||||||
|
|
||||||
|
#undef DEBUG_PAM
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#define ACTION_ADD_HMAC_CHALRESP "add_hmac_chalresp"
|
||||||
|
|
||||||
|
const char *usage =
|
||||||
|
"Usage: ykpamcfg [options]\n"
|
||||||
|
"\n"
|
||||||
|
"Options :\n"
|
||||||
|
"\n"
|
||||||
|
"\t-1 Send challenge to slot 1. This is the default.\n"
|
||||||
|
"\t-2 Send challenge to slot 2.\n"
|
||||||
|
"\t-A action What to do.\n"
|
||||||
|
"\n"
|
||||||
|
"\t-v verbose\n"
|
||||||
|
"\t-h help (this text)\n"
|
||||||
|
"\n"
|
||||||
|
"Actions :\n"
|
||||||
|
"\n"
|
||||||
|
"\t" ACTION_ADD_HMAC_CHALRESP "\tAdds a challenge-response state file for a connected YubiKey (default)\n"
|
||||||
|
"\n"
|
||||||
|
"\n"
|
||||||
|
;
|
||||||
|
const char *optstring = "12A:vh";
|
||||||
|
|
||||||
|
static void
|
||||||
|
report_yk_error()
|
||||||
|
{
|
||||||
|
if (ykp_errno)
|
||||||
|
fprintf(stderr, "Yubikey personalization error: %s\n",
|
||||||
|
ykp_strerror(ykp_errno));
|
||||||
|
if (yk_errno) {
|
||||||
|
if (yk_errno == YK_EUSBERR) {
|
||||||
|
fprintf(stderr, "USB error: %s\n",
|
||||||
|
yk_usb_strerror());
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Yubikey core error: %s\n",
|
||||||
|
yk_strerror(yk_errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
parse_args(int argc, char **argv,
|
||||||
|
int *slot, bool *verbose,
|
||||||
|
unsigned char **action,
|
||||||
|
int *exit_code)
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
|
||||||
|
while((c = getopt(argc, argv, optstring)) != -1) {
|
||||||
|
switch (c) {
|
||||||
|
case '1':
|
||||||
|
*slot = 1;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
*slot = 2;
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
*action = optarg;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
*verbose = true;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
default:
|
||||||
|
fputs(usage, stderr);
|
||||||
|
*exit_code = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
do_add_hmac_chalresp(YK_KEY *yk, uint8_t slot, bool verbose, unsigned char *output_dir, int *exit_code)
|
||||||
|
{
|
||||||
|
unsigned char buf[CR_RESPONSE_SIZE + 16];
|
||||||
|
CR_STATE state;
|
||||||
|
unsigned int flags = 0;
|
||||||
|
int ret = 0;
|
||||||
|
unsigned int response_len;
|
||||||
|
char *fn;
|
||||||
|
struct passwd *p;
|
||||||
|
FILE *f = NULL;
|
||||||
|
|
||||||
|
state.slot = slot;
|
||||||
|
flags |= YK_FLAG_MAYBLOCK;
|
||||||
|
*exit_code = 1;
|
||||||
|
|
||||||
|
p = getpwuid (getuid ());
|
||||||
|
|
||||||
|
if (! p) {
|
||||||
|
fprintf (stderr, "Who am I???");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! get_user_challenge_file(yk, output_dir, p->pw_name, &fn)) {
|
||||||
|
fprintf (stderr, "Failed getting chalresp state filename\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generate_random(state.challenge, CR_CHALLENGE_SIZE)) {
|
||||||
|
fprintf (stderr, "FAILED getting %i bytes of random data\n", CR_CHALLENGE_SIZE);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
state.challenge_len = CR_CHALLENGE_SIZE;
|
||||||
|
|
||||||
|
if (! challenge_response(yk, state.slot, state.challenge, CR_CHALLENGE_SIZE,
|
||||||
|
true, flags, verbose,
|
||||||
|
buf, sizeof(buf), &response_len))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (response_len > sizeof (state.response)) {
|
||||||
|
fprintf (stderr, "Got too long response ??? (%i/%i)", response_len, sizeof(state.response));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
memcpy (state.response, buf, response_len);
|
||||||
|
state.response_len = response_len;
|
||||||
|
|
||||||
|
f = fopen (fn, "w");
|
||||||
|
if (! f) {
|
||||||
|
fprintf (stderr, "Failed opening '%s' for writing : %s\n", fn, strerror (errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! write_chalresp_state (f, &state))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
printf ("Stored initial challenge and expected response in '%s'.\n", fn);
|
||||||
|
|
||||||
|
*exit_code = 0;
|
||||||
|
ret = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (f)
|
||||||
|
fclose (f);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
YK_KEY *yk = NULL;
|
||||||
|
bool error = true;
|
||||||
|
int exit_code = 0;
|
||||||
|
|
||||||
|
/* Options */
|
||||||
|
bool verbose = false;
|
||||||
|
unsigned char *action = ACTION_ADD_HMAC_CHALRESP;
|
||||||
|
int slot = 1;
|
||||||
|
|
||||||
|
ykp_errno = 0;
|
||||||
|
yk_errno = 0;
|
||||||
|
|
||||||
|
if (! parse_args(argc, argv,
|
||||||
|
&slot, &verbose,
|
||||||
|
&action,
|
||||||
|
&exit_code))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
exit_code = 1;
|
||||||
|
|
||||||
|
if (! strcmp(action, ACTION_ADD_HMAC_CHALRESP)) {
|
||||||
|
/*
|
||||||
|
* Set up challenge-response login authentication
|
||||||
|
*/
|
||||||
|
if (! init_yubikey (&yk))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (! check_firmware_version(yk, verbose, false))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
if (! do_add_hmac_chalresp (yk, slot, verbose, NULL, &exit_code))
|
||||||
|
goto err;
|
||||||
|
} else {
|
||||||
|
fprintf (stderr, "Unknown action '%s'\n", action);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_code = 0;
|
||||||
|
error = false;
|
||||||
|
|
||||||
|
err:
|
||||||
|
if (error || exit_code != 0) {
|
||||||
|
report_yk_error ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (yk && !yk_close_key (yk)) {
|
||||||
|
report_yk_error ();
|
||||||
|
exit_code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!yk_release ()) {
|
||||||
|
report_yk_error ();
|
||||||
|
exit_code = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit (exit_code);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user