mirror of
https://github.com/Yubico/yubico-pam.git
synced 2024-12-01 15:24:12 +01:00
Add ykpamcfg - C/R setup command line utility.
This commit is contained in:
parent
c1f8ba8804
commit
e2968a1bf8
11
Makefile.am
11
Makefile.am
@ -40,6 +40,17 @@ pam_yubico_la_CPPFLAGS = @YKPERS_CFLAGS@
|
||||
|
||||
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.
|
||||
|
||||
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…
Reference in New Issue
Block a user