ootp-snap-05-15-2011-r184 imported

This commit is contained in:
Alexandre Dulaunoy 2017-01-03 12:16:53 +01:00
parent 9a903d7a74
commit b48b72effd
72 changed files with 3354 additions and 916 deletions

1
VERSION Normal file
View file

@ -0,0 +1 @@
snap-r184

View file

@ -24,7 +24,7 @@
' OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
' SUCH DAMAGE.
'
' $Id: HOTPC.BAS 92 2009-12-28 02:45:54Z maf $
' $Id: HOTPC.BAS 148 2011-03-31 00:46:42Z maf $
'
#include "sha-1.def"
#include "preader.def"
@ -56,6 +56,7 @@ Const HOTPNum = 50
' to global, reorg balance reader code
' naming consistency, default 50 systems
' Rev 8 - release Rev7
' Rev 9 - CheckPIN for GetHOTP*, myReaderKey
' 20 byte scratch area addressable as 5 32bit vars
public str20 as String*20
@ -83,7 +84,7 @@ public u32b3 as Byte at u32+3
public HOTPfmt as Byte
' Code version
Const HOTPCodeVersion = 8
Const HOTPCodeVersion = 9
' Capabilities (conditionally compiled in functions)
eeprom Capabilities as Long = CAPSETHOST + CAPGETHOST + CAPGETHOSTNAME + _
@ -153,7 +154,7 @@ eeprom eestr20 as String*20
eeprom PIN as String*5 = DefaultPIN
' Reader Key. Weak authentication for reader
eeprom readerKey as String*5 = "00000"
eeprom ReaderKey as String*5 = "00000"
' The balance card can only use one of the host definitions.
eeprom BalanceCardIndex = 255 ' Disabled
@ -163,17 +164,17 @@ eeprom AdminMode as Byte = 1
' Keep track of PIN failures
eeprom PINFailCount as Byte = 0
eeprom readerKeyFailCount as Byte = 0
eeprom ReaderKeyFailCount as Byte = 0
Const MaxPINFail = 10
Const MaxReaderKeyFail = 2
declare Sub Truncate(Idx as Byte)
declare Sub HOTPCommon(ReadOnly Idx as Byte, ReadOnly Count as Long, _
ReadOnly myPIN as String*5, ReadOnly readerKey as String*5)
ReadOnly myPIN as String*5, ReadOnly myReaderKey as String*5)
declare Function CheckReaderKey(ReadOnly Idx as Byte, _
ReadOnly myKey as String*5) as Byte
ReadOnly myReaderKey as String*5) as Byte
declare Function CheckPIN(ReadOnly myPIN as String*5) as Byte
@ -184,7 +185,7 @@ declare Function CheckIndex(Idx as Byte) as Byte
' Common HOTP generation code
Sub HOTPCommon(ReadOnly Idx as Byte, ReadOnly Count32 as Long, _
ReadOnly myPIN as String*5, ReadOnly readerKey as String*5)
ReadOnly myPIN as String*5, ReadOnly myReaderKey as String*5)
' disable admin mode on first use.
if (AdminMode = 1) then
@ -196,9 +197,15 @@ Sub HOTPCommon(ReadOnly Idx as Byte, ReadOnly Count32 as Long, _
SW1SW2 = swAccessDenied
Exit
end if
' check PIN
if CheckPIN(myPIN) <> 0 then
SW1SW2 = swAccessDenied
Exit
end if
' Check reader access
if CheckReaderKey(Idx, readerKey) <> 0 then
if CheckReaderKey(Idx, myReaderKey) <> 0 then
SW1SW2 = swAccessDenied
Exit
end if
@ -300,7 +307,6 @@ Function CheckPIN(ReadOnly myPIN as String*5) as Byte
if AdminMode = 1 then
CheckPIN = 0 ' success
PINFailCount = 0 ' reset
else
if PINFailCount >= MaxPINFail then
CheckPIN = 2 ' fail
@ -318,18 +324,20 @@ Function CheckPIN(ReadOnly myPIN as String*5) as Byte
End Function ' CheckPIN
Function CheckReaderKey(ReadOnly Idx as Byte, _
ReadOnly myKey as String*5) as Byte
ReadOnly myReaderKey as String*5) as Byte
if (Asc(HOTPHost(Idx)(2)) AND &H80) then
if myKey <> readerKey then
readerKeyFailCount = readerKeyFailCount + 1
if (readerKeyFailCount >= MAXReaderKeyFail) then
PINFailCount = MaxPINFail ' Lock card
end if
CheckReaderKey = 1 ' Fail
if (ReaderKeyFailCount >= MAXReaderKeyFail) then
PINFailCount = MaxPINFail ' Lock card
CheckReaderKey = 1 ' fail
else
readerKeyFailCount = 0
CheckReaderKey = 0 ' Success
if myReaderKey <> ReaderKey then
CheckReaderKey = 1 ' Fail
ReaderKeyFailCount = ReaderKeyFailCount + 1
else
CheckReaderKey = 0 ' Success
ReaderKeyFailCount = 0 ' reset on good key
end if
end if
else
CheckReaderKey = 0 'Success
@ -466,6 +474,11 @@ Command &H80 &H48 SetAdminMode(Mode as Byte, K as String*20)
AdminMode = Mode
end if
if AdminMode = 1 then
ReaderKeyFailCount = 0 ' reset
PINFailCount = 0 ' reset
end if
End Command ' SetAdminMode
#endif 'ENABLECSETADMINMODE
@ -628,7 +641,7 @@ End Command ' GetHOTPHost
Command &H80 &H5C GetHOTPHostCount32(Idx as Byte, myPIN as String*5,_
Count32 as Long, HOTP as String*5, HostName as String*12)
Call HOTPCommon(Idx, Count32, myPIN, readerKey)
Call HOTPCommon(Idx, Count32, myPIN, HOTP)
HOTP = HOTPTruncated
HostName = HOTPHost(Idx)
@ -656,7 +669,7 @@ Command &H80 &H5E ClearAll()
PINFailCount = 0
readerKeyFailCount = 0
ReaderKeyFailCount = 0
AdminMode = 1
@ -667,18 +680,18 @@ Command &H80 &H5E ClearAll()
End Command ' ClearAll
#endif 'ENABLECCLEARALL
#ifdef ENABLESETREADERKEY
Command &H80 &H60 SetReaderKey(myKey as String*5)
#ifdef ENABLESETReaderKey
Command &H80 &H60 SetReaderKey(myReaderKey as String*5)
if CheckAdmin() <> 0 then
SW1SW2 = swAccessDenied
Exit
else
ReaderKey = myReaderKey
end if
readerKey = myKey
End Command ' SetReaderKey
#endif 'ENABLECSETREADERKEY
#endif 'ENABLECSETReaderKey
Command &H80 &H90 GetCapabilities(C as Long)

Binary file not shown.

View file

@ -1,4 +1,4 @@
# $Id: Makefile 13 2009-11-26 16:37:03Z maf $
# $Id: Makefile 127 2010-06-15 14:24:34Z maf $
what:
@echo
@ -25,22 +25,27 @@ INSTALL=install -c -m0755
.c.o:; $(CC) $(CFLAGS) -c $*.c -o $*.o
OBJS = ../common/xerr.o ../common/str.o ../common/acr30.o ../common/scr.o ../common/sccmd.o
BINS = bcload
BIN = bcload
COBJS = ../common/xerr.o ../common/str.o ../common/acr30.o ../common/scr.o ../common/sccmd.o
OBJS = version.o ${BIN}.o
BINDIR=/usr/local/ootp/bin
all: bcload.c ${OBJS} ${BINS}
all: version ${COBJS} ${OBJS} ${BIN}
version:
rm -f version.c; ../build/version ../VERSION ${BIN} > version.c
version.c:
install:
mkdir -p ${BINDIR}
${INSTALL} ${BINS} ${BINDIR}
${INSTALL} ${BIN} ${BINDIR}
@echo files installed in ${BINDIR}
clean:
/bin/rm -f ${BINS} bcload.o
/bin/rm -f ${BIN} ${OBJS} version.c
bcload: ${OBJS} bcload.o
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o bcload ${OBJS} bcload.o $(LIBS)
${BIN}: ${COBJS} ${OBJS}
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o ${BIN} ${COBJS} ${OBJS} $(LIBS)

View file

@ -26,7 +26,7 @@
*
* Ported from ZeitControl bcload.bas and download.bas sample source
*
* $Id: bcload.c 90 2009-12-28 02:44:52Z maf $
* $Id: bcload.c 127 2010-06-15 14:24:34Z maf $
*/
#include <sys/cdefs.h>
@ -34,6 +34,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <getopt.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
@ -98,6 +99,7 @@ void bcimg_read_eeprom_section(struct bcimg *bcimg, uint16_t *img_EEAddr,
int main(int argc, char **argv)
{
extern char *ootp_version;
struct scr_ctx *scrctx;
struct bcimg bcimg;
uint32_t chunk_start, bytes_left, chunk_working;
@ -109,13 +111,28 @@ int main(int argc, char **argv)
uint8_t img_state, *img_pgmdata, img_EELoadLen, sname[4];
uint8_t sc_EEStart[2], sc_EELen[2], sc_EEAddr[2];
uint8_t sc_state, sc_version[256], sc_version_len, sc_CRC[2];
int i, r;
int i, r, opt_version;
int list_readers, verbose, paranoid, force_test;
char *reader, *endptr, *c, *img_fname;
struct option longopts[] = {
{ "debug", 1, (void*)0L, 'd'},
{ "image", 1, (void*)0L, 'f'},
{ "help", 0, (void*)0L, 'h'},
{ "help", 0, (void*)0L, '?'},
{ "list-readers", 0, (void*)0L, 'l'},
{ "no-paranoid", 0, (void*)0L, 'p'},
{ "reader", 1, (void*)0L, 'r'},
{ "force-test", 0, (void*)0L, 't'},
{ "verbose", 0, (void*)0L, 'v'},
{ "version", 0, &opt_version, 1},
{ 0, 0, 0, 0},
};
/* init xerr */
xerr_setid(argv[0]);
opt_version = 0;
force_test = 0;
paranoid = 1;
debug = 0;
@ -126,7 +143,8 @@ int main(int argc, char **argv)
img_fname = "HOTPC.IMG";
bzero(&bcimg, sizeof bcimg);
while ((i = getopt(argc, argv, "d:f:hlpr:tv?")) != -1) {
while ((i = getopt_long(argc, argv, "d:f:hlpr:tv?", longopts,
(int*)0L)) != -1) {
switch (i) {
@ -144,7 +162,7 @@ int main(int argc, char **argv)
case '?':
help();
exit(0);
break; /* notreached */
break; /* not reached */
case 'l':
list_readers = 1;
@ -166,6 +184,17 @@ int main(int argc, char **argv)
verbose = 1;
break;
case 0:
if (opt_version) {
printf("%s\n", ootp_version);
exit(0);
}
break;
default:
xerr_errx(1, "getopt_long(): fatal.");
break; /* not reached */
} /* switch */
} /* while getopt() */
@ -510,7 +539,7 @@ main_out:
void help(void)
{
fprintf(stderr, "bcload [hlptv?] [-d debug_level] [-f fname] [-r reader]\n");
fprintf(stderr, "bcload [hlptv?] [-d debug_level] [-f image] [-r reader]\n");
fprintf(stderr, " -h : help\n");
fprintf(stderr, " -l : list SC readers\n");
fprintf(stderr, " -t : force to TEST state\n");

29
build/version Executable file
View file

@ -0,0 +1,29 @@
#!/bin/sh
ME=`whoami`
DATE=`date`
HOST=`hostname`
if [ "X$1" = "X" ]; then
echo "Usage: version <idfile> <program>" 1>&2
exit 1
fi
if [ "X$2" = "X" ]; then
PGM="ootp"
else
PGM="$2"
fi
# if VERSION file exists, then this is a snapshot or release build,
if [ -e $1 ]; then
R=`cat $1`
# else assume building in sandbox
else
SVN=`which svn`
RR=`svn info | grep "^Repository Root:" | awk '{print $3}'`
R=`svn info $RR | grep "^Revision:" | awk '{print $2}'`
R="devel r$R"
fi
echo "char *ootp_version = \"$PGM $R $ME@$HOST $DATE\";"

View file

@ -1,4 +1,4 @@
# $Id: Makefile 13 2009-11-26 16:37:03Z maf $
# $Id: Makefile 134 2010-06-15 14:31:25Z maf $
what:
@echo

View file

@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: ffdb.c 13 2009-11-26 16:37:03Z maf $
* $Id: ffdb.c 117 2010-03-08 04:24:07Z maf $
*/
#include <sys/fcntl.h>
@ -504,6 +504,7 @@ struct ffdb_ctx *ffdb_db_open(char *base_dir_pn, size_t max_key_size,
else
verbose = 0;
ffdbctx = (struct ffdb_ctx*)0L;
ret = -1; /* fail */
base_dir_pn_size = strlen(base_dir_pn) + 1;

View file

@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: otplib.c 84 2009-12-27 17:29:51Z maf $
* $Id: otplib.c 174 2011-05-16 02:09:26Z maf $
*/
#include <openssl/ssl.h>
@ -34,9 +34,13 @@
#include <sys/errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -49,11 +53,15 @@
#include "otpsc.h"
char *otp_status_l[] = {"error", "active", "inactive", "disabled"};
char *otp_format_l[] = {"error", "hex40", "dhex40", "dec31.6", "dec31.7",
"dec31.8", "dec31.9", "dec31.10"};
char *otp_type_l[] = {"error", "HOTP"};
char *otp_flags_l[] = {"display-count"};
char *otp_flags_l[] = {"display-count", "send-token"};
char *sc_flags_l[] = {"challenge","readerkey"};
/*
* One Time Password library with HOTP implementation.
@ -86,6 +94,7 @@ char *otp_flags_l[] = {"display-count"};
* otp_user_exists() user exists in OTP db?
* otp_user_rm() remove user from OTP db
* otp_user_auth() authenticate user from OTP db
* otp_user_send_token() send token to user via some OOB method
*
****
*
@ -180,6 +189,17 @@ int otp_ou_toascii(struct otp_ctx *otpctx, struct otp_user *ou)
str_hex_dump(c, (void*)&ou->last, 8);
c += 16;
if ((n = strlen(ou->loc)) > OTP_USER_LOC_LEN) {
xerr_warnx("otp_ou_toascii(): location length invalid.");
return -1;
}
*c++ = ':';
if (n) {
strcpy(c, ou->loc);
c += n;
}
*c++ = 0;
#if BYTE_ORDER == LITTLE_ENDIAN
@ -211,7 +231,7 @@ int otp_ou_toascii(struct otp_ctx *otpctx, struct otp_user *ou)
*/
int otp_ou_fromascii(struct otp_ctx *otpctx, struct otp_user *ou)
{
int field, ret, n, i;
int field, ret, n, i, n_fields, l_field;
char *c;
if (otp_db_valid(otpctx, "otp_ou_fromascii") < 0)
@ -237,7 +257,7 @@ int otp_ou_fromascii(struct otp_ctx *otpctx, struct otp_user *ou)
*c = 0;
++c;
++field;
if (field > (OTP_USER_N_FIELDS-1)) /* too many fields */
if (field > (OTP_USER_N_FIELDS_MAX-1)) /* too many fields */
break;
} else if (*c == 0) {
break;
@ -246,12 +266,18 @@ int otp_ou_fromascii(struct otp_ctx *otpctx, struct otp_user *ou)
}
}
if (field != (OTP_USER_N_FIELDS-1)) {
/* last field does not have a : */
if ((field > OTP_USER_N_FIELDS_MAX-1) ||
(field < OTP_USER_N_FIELDS_MIN-1)) {
if (otpctx->verbose)
xerr_warnx("expecting %d fields, got %d.", OTP_USER_N_FIELDS, field+1);
xerr_warnx("expecting min=%d max=%d fields, got %d.",
OTP_USER_N_FIELDS_MIN, OTP_USER_N_FIELDS_MAX, field+1);
return -1;
}
/* look ahead */
l_field = field;
#define CHK_STRLEN(N,L)\
n = strlen(c);\
if (n != L) {\
@ -274,8 +300,11 @@ int otp_ou_fromascii(struct otp_ctx *otpctx, struct otp_user *ou)
xerr_warnx("%s: str_hex_decode(%s): failed.", __func__, N);\
goto otp_ou_fromascii_out;\
}\
/* may be changed after reading version field */
n_fields = OTP_USER_N_FIELDS;
for (field = 0, c = ou->ascii_encoded; field < OTP_USER_N_FIELDS; ++field) {
for (field = 0, c = ou->ascii_encoded; field < n_fields; ++field) {
if (field == 0) { /* version */
CHK_STRLEN("version", 2)
@ -287,8 +316,20 @@ int otp_ou_fromascii(struct otp_ctx *otpctx, struct otp_user *ou)
OTP_VERSION_MAX);
return -1;
}
if (ou->version == 1)
n_fields = OTP_USER_N_FIELDS_V1;
if ((ou->version == 1) && (l_field != OTP_USER_N_FIELDS_V1-1)) {
xerr_warnx("v1 format has %d fields, not %d.",
OTP_USER_N_FIELDS_V1, l_field+1);
return -1;
}
if ((ou->version == 2) && (l_field != OTP_USER_N_FIELDS_V2-1)) {
xerr_warnx("v2 format has %d fields, not %d.",
OTP_USER_N_FIELDS_V2, l_field+1);
return -1;
}
} else if (field == 1) { /* username */
CHK_STRRANGE("username", 1, 32)
CHK_STRRANGE("username", 1, OTP_USER_NAME_LEN)
strcpy(ou->username, c);
} else if (field == 2) { /* key */
CHK_STRRANGE("key", 1, 40);
@ -314,7 +355,10 @@ int otp_ou_fromascii(struct otp_ctx *otpctx, struct otp_user *ou)
} else if (field == 9) { /* last */
CHK_STRLEN("last", 16);
HEX_DECODE("last", last, 16)
}
} else if (field == 10) { /* location */
CHK_STRRANGE("loc", 0, OTP_USER_LOC_LEN)
strcpy(ou->loc, c);
}
/* skip to next field */
for (; *c; ++c);
@ -333,6 +377,9 @@ int otp_ou_fromascii(struct otp_ctx *otpctx, struct otp_user *ou)
ou->db_key.key = &ou->username;
ou->db_key.size = strlen(ou->username);
/* up convert */
ou->version = OTP_VERSION;
ret = OTP_SUCCESS;
otp_ou_fromascii_out:
@ -730,6 +777,7 @@ struct otp_ctx *otp_db_open(char *dbname, int flags)
bzero(otpctx, sizeof *otpctx);
otpctx->verbose = verbose;
otpctx->send_token_pathname = OTP_SEND_TOKEN_PATHNAME;
if (!(otpctx->ffdbctx = ffdb_db_open(dbname, OTP_USER_NAME_LEN,
OTP_USER_ASCII_LEN, ffdb_flags, S_IRUSR|S_IWUSR, S_IRWXU))) {
@ -922,6 +970,7 @@ int otp_db_load(struct otp_ctx *otpctx, char *u_username)
return -1;
ret = -1; /* fail */
bzero(&ou, sizeof(ou));
while (!feof(stdin)) {
@ -1021,6 +1070,7 @@ otp_db_load_out:
* arguments:
* otpctx - otp db context returned by otp_db_open()
* u_username - username
* u_loc - location
* u_key_val - key value
* u_key_size - length of key in bytes
* u_count - initial count
@ -1036,9 +1086,9 @@ otp_db_load_out:
*
*/
int otp_user_add(struct otp_ctx *otpctx, char *u_username,
uint8_t *u_key_val, uint16_t u_key_size, uint64_t u_count,
uint64_t u_count_ceil, uint8_t u_status, uint8_t u_type,
uint8_t u_format, uint8_t u_version)
char *u_loc, uint8_t *u_key_val, uint16_t u_key_size,
uint64_t u_count, uint64_t u_count_ceil, uint8_t u_status,
uint8_t u_type, uint8_t u_format, uint8_t u_version)
{
struct otp_user ou;
int ret, r;
@ -1066,11 +1116,19 @@ int otp_user_add(struct otp_ctx *otpctx, char *u_username,
goto otp_user_add_out;
}
if (strlen(u_loc) > OTP_USER_LOC_LEN) {
if (otpctx->verbose)
xerr_warnx("strlen(u_loc) > OTP_USER_LOC_LEN.");
goto otp_user_add_out;
}
/*
* copy in user fields to ou
*/
strcpy(ou.username, u_username);
/* lengths checked above */
strncpy(ou.username, u_username, OTP_USER_NAME_LEN);
strncpy(ou.loc, u_loc, OTP_USER_LOC_LEN);
bcopy(u_key_val, &ou.key, u_key_size);
ou.key_size = u_key_size;
ou.count = u_count;
@ -1162,13 +1220,15 @@ int otp_user_exists(struct otp_ctx *otpctx, char *u_username)
if (otp_db_valid(otpctx, "otp_user_exists") < 0)
return -1;
/* paranoia */
str_safe(u_username, OTP_USER_NAME_LEN);
ret = OTP_ERROR; /* fail */
db_key.key = u_username;
db_key.size = strlen(u_username);
/* paranoia */
str_safe(u_username, OTP_USER_NAME_LEN, ".", STR_SAFE_CHECK_LEN|
STR_SAFE_CHECK_ALPHA|STR_SAFE_CHECK_SET|STR_SAFE_CHECK_NUM|
STR_SAFE_FIX|STR_SAFE_WARN);
/*
* sanity checks
*/
@ -1213,14 +1273,15 @@ int otp_user_rm(struct otp_ctx *otpctx, char *u_username)
if (otp_db_valid(otpctx, "otp_user_rm") < 0)
return -1;
/* paranoia */
str_safe(u_username, OTP_USER_NAME_LEN);
ret = -1; /* fail */
db_key.key = u_username;
db_key.size = strlen(u_username);
/* paranoia */
str_safe(u_username, OTP_USER_NAME_LEN, ".", STR_SAFE_CHECK_LEN|
STR_SAFE_CHECK_ALPHA|STR_SAFE_CHECK_SET|STR_SAFE_CHECK_NUM|
STR_SAFE_FIX|STR_SAFE_WARN);
/*
* sanity checks
*/
@ -1275,8 +1336,12 @@ int otp_user_auth(struct otp_ctx *otpctx, char *u_username,
(OTP_HOTP_HEX40_LEN<<1) : OTP_HOTP_DEC31_LEN;
/* paranoia */
str_safe(u_username, OTP_USER_NAME_LEN);
str_safe(u_crsp, crsp_max<<1);
str_safe(u_username, OTP_USER_NAME_LEN, ".", STR_SAFE_CHECK_LEN|
STR_SAFE_CHECK_ALPHA|STR_SAFE_CHECK_SET|
STR_SAFE_CHECK_NUM|STR_SAFE_FIX|STR_SAFE_WARN);
str_safe(u_crsp, crsp_max<<1, (char*)0L, STR_SAFE_CHECK_LEN|
STR_SAFE_CHECK_ALPHA|STR_SAFE_CHECK_NUM|STR_SAFE_FIX|STR_SAFE_WARN);
/* open user record */
if (otp_urec_open(otpctx, u_username, &ou, O_RDWR, FFDB_OP_LOCK_EX) < 0) {
@ -1356,6 +1421,111 @@ otp_user_auth_out:
} /* otp_user_auth */
/*
* otp_user_send_token
*
* returns: <0 failure
*/
int otp_user_send_token(struct otp_ctx *otpctx, char *u_username,
char *service)
{
struct sockaddr_un tx_path;
char crsp_tmp[32], tx_buf[1024];
struct otp_user ou;
int ret, r, tx_sock, tx_buf_len;
if (otp_db_valid(otpctx, "otp_user_send") < 0)
return -1;
ret = -1; /* fail */
tx_sock = -1;
bzero(&ou, sizeof ou);
/* paranoia */
str_safe(u_username, OTP_USER_NAME_LEN, ".", STR_SAFE_CHECK_LEN|
STR_SAFE_CHECK_ALPHA|STR_SAFE_CHECK_SET| STR_SAFE_CHECK_NUM|
STR_SAFE_FIX|STR_SAFE_WARN);
/* open user record */
if (otp_urec_open(otpctx, u_username, &ou, O_RDWR, FFDB_OP_LOCK_EX) < 0) {
if (otpctx->verbose)
xerr_warnx("otp_urec_open(%s): failed.", u_username);
goto otp_user_send_token_out;
}
/* get user record */
if (otp_urec_get(otpctx, &ou) < 0) {
if (otpctx->verbose)
xerr_warnx("otp_urec_get(%s): failed.", u_username);
goto otp_user_send_token_out;
}
if (otp_urec_sanity(otpctx, &ou) < 0) {
if (otpctx->verbose)
xerr_warnx("otp_urec_sanity(): failed.");
goto otp_user_send_token_out;
}
/* generate next token */
if (otp_urec_crsp(otpctx, &ou, 0, crsp_tmp, sizeof(crsp_tmp)) < 0) {
if (otpctx->verbose)
xerr_warnx("otp_urec_crsp(): failed.");
goto otp_user_send_token_out;
}
/* format tx buffer */
if ((tx_buf_len = snprintf(tx_buf, sizeof(tx_buf), "%s\n%s\n%s\n%s\n",
service, ou.username, ou.loc, crsp_tmp)) >= sizeof(tx_buf)) {
if (otpctx->verbose)
xerr_warnx("snprintf(tx_buf): overflow");
goto otp_user_send_token_out;
}
/* setup to transmit UDP datagram */
if ((tx_sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
if (otpctx->verbose)
xerr_warn("socket(AF_UNIX, SOCK_DGRAM)");
goto otp_user_send_token_out;
}
bzero(&tx_path, sizeof (tx_path));
tx_path.sun_family = AF_UNIX;
if (strlen(otpctx->send_token_pathname) >= sizeof (tx_path.sun_path)) {
xerr_warnx("send_token_pathname too long.");
goto otp_user_send_token_out;
}
strncpy(tx_path.sun_path, otpctx->send_token_pathname,
sizeof(tx_path.sun_path));
/* send token */
if (sendto(tx_sock, tx_buf, tx_buf_len+1, 0, (struct sockaddr*)&tx_path,
sizeof(tx_path)) < 0) {
if (otpctx->verbose)
xerr_warn("sendto(%s)", otpctx->send_token_pathname);
goto otp_user_send_token_out;
}
/* success */
ret = 0;
otp_user_send_token_out:
if (tx_sock != -1)
close(tx_sock);
/* close record */
if (ou.db_key.fd && (ou.db_key.fd != -1)) {
if ((r = otp_urec_close(otpctx, &ou)) < 0) {
if (otpctx->verbose)
xerr_warnx("otp_urec_close(): failed.");
ret = r;
}
}
return ret;
} /* otp_user_send_token */
/*
* function: otp_urec_open()
*
@ -1405,13 +1575,15 @@ int otp_urec_open(struct otp_ctx *otpctx, char *u_username,
if (otp_db_valid(otpctx, "otp_urec_open") < 0)
return -1;
/* paranoia */
str_safe(u_username, OTP_USER_NAME_LEN);
ret = -1; /* fail */
bzero(ou, sizeof *ou);
ou->db_key.fd = -1; /* invalid */
/* paranoia */
str_safe(u_username, OTP_USER_NAME_LEN, ".", STR_SAFE_CHECK_LEN|
STR_SAFE_CHECK_ALPHA|STR_SAFE_CHECK_SET|STR_SAFE_CHECK_NUM|
STR_SAFE_FIX|STR_SAFE_WARN);
ou->db_key.key = u_username;
ou->db_key.size = strlen(u_username);
@ -1716,6 +1888,8 @@ void otp_urec_disp(struct otp_ctx *otpctx, struct otp_user *ou)
str_hex_dump(tmp, ou->key, 20);
printf("Username.......%s\n", ou->username);
if (ou->loc[0])
printf("Location.......%s\n", ou->loc);
printf("Key............%s\n", tmp);
printf("Count..........%" PRIu64 " (0x%" PRIx64 ")\n", ou->count, ou->count);
printf("Count Ceiling..%" PRIu64 " (0x%" PRIx64 ")\n", ou->count_ceil,
@ -1772,6 +1946,51 @@ uint8_t sc_index, char *sc_hostname, uint8_t *sc_flags)
for (l = 0; l < SC_HOSTNAME_LEN; ++l)
tmp_sc_hostname[l] |= sc_flags[l];
/* format is encoded in flag bits */
if ((ou->format == OTP_FORMAT_DEC31_6) ||
(ou->format == OTP_FORMAT_DEC31_7) ||
(ou->format == OTP_FORMAT_DEC31_8) ||
(ou->format == OTP_FORMAT_DEC31_9) ||
(ou->format == OTP_FORMAT_DEC31_10))
tmp_sc_hostname[HOSTNAME_POS_FMT] |= HOSTNAME_FLAG_MASK;
if (ou->format == OTP_FORMAT_HEX40) {
tmp_sc_hostname[HOSTNAME_POS_FMT3] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT2] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT1] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT0] &= ~HOSTNAME_FLAG_MASK;
} else if (ou->format == OTP_FORMAT_DHEX40) {
tmp_sc_hostname[HOSTNAME_POS_FMT3] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT2] |= HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT1] |= HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT0] |= HOSTNAME_FLAG_MASK;
} else if (ou->format == OTP_FORMAT_DEC31_6) {
tmp_sc_hostname[HOSTNAME_POS_FMT3] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT2] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT1] |= HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT0] &= ~HOSTNAME_FLAG_MASK;
} else if (ou->format == OTP_FORMAT_DEC31_7) {
tmp_sc_hostname[HOSTNAME_POS_FMT3] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT2] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT1] |= HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT0] |= HOSTNAME_FLAG_MASK;
} else if (ou->format == OTP_FORMAT_DEC31_8) {
tmp_sc_hostname[HOSTNAME_POS_FMT3] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT2] |= HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT1] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT0] &= ~HOSTNAME_FLAG_MASK;
} else if (ou->format == OTP_FORMAT_DEC31_9) {
tmp_sc_hostname[HOSTNAME_POS_FMT3] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT2] |= HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT1] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT0] |= HOSTNAME_FLAG_MASK;
} else if (ou->format == OTP_FORMAT_DEC31_10) {
tmp_sc_hostname[HOSTNAME_POS_FMT3] &= ~HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT2] |= HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT1] |= HOSTNAME_FLAG_MASK;
tmp_sc_hostname[HOSTNAME_POS_FMT0] &= ~HOSTNAME_FLAG_MASK;
}
tmpc32 = ou->count;
#if BYTE_ORDER == LITTLE_ENDIAN

View file

@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: otplib.h 61 2009-12-17 03:57:22Z maf $
* $Id: otplib.h 174 2011-05-16 02:09:26Z maf $
*/
#include <sys/types.h>
@ -69,7 +69,7 @@
#define OTP_DB_FNAME "/etc/otpdb" /* location of user database */
#define OTP_VERSION 1 /* version of library */
#define OTP_VERSION 2 /* version of library */
#define OTP_FORMAT_HEX40 1 /* 40 bits in hex */
#define OTP_FORMAT_DHEX40 2 /* 40 bits in hex w. RFC 4226 DT */
@ -87,7 +87,7 @@
#define OTP_WINDOW_MAX 255 /* max challenge window */
#define OTP_VERSION_MIN 1 /* min version for this code */
#define OTP_VERSION_MAX 1 /* max version for this code */
#define OTP_VERSION_MAX 2 /* max version for this code */
#define OTP_HOTP_KEY_SIZE 20 /* HMAC SHA160 key length */
#define OTP_HOTP_HEX40_LEN 5 /* HOTP challenge hex 40 bits */
@ -105,14 +105,22 @@
#define OTP_STATUS_MAX 3 /* highest valid status enum */
#define OTP_USER_N_FIELDS 10 /* n fields in ASCII encoding */
#define OTP_USER_ASCII_LEN 139 /* max ASCII encoded length (w/o null) */
#define OTP_USER_N_FIELDS 11 /* n fields in ASCII encoding */
#define OTP_USER_N_FIELDS_V1 10 /* n fields in ASCII encoding for v1 */
#define OTP_USER_N_FIELDS_V2 11 /* n fields in ASCII encoding for v2 */
#define OTP_USER_ASCII_LEN 180 /* max ASCII encoded length (w/o null) */
#define OTP_USER_N_FIELDS_MAX 11 /* max # fields (all versions */
#define OTP_USER_N_FIELDS_MIN 10 /* min # fields (all versions */
#define OTP_FLAGS_DSPCNT 0x1 /* force display count */
#define OTP_FLAGS_BITS 1 /* bits used */
#define OTP_FLAGS_SEND_TOKEN 0x2 /* execute send token script for user */
#define OTP_FLAGS_BITS 2 /* bits used */
#define OTP_SEND_TOKEN_PATHNAME "/var/run/otp-tokend"
#define OTP_USER_NAME_LEN 32 /* max length of username (w/o null)*/
#define OTP_USER_KEY_LEN 64 /* key length */
#define OTP_USER_LOC_LEN 40 /* locatation identifier */
#define OTP_DB_VERBOSE 0x01 /* verbose error messages */
#define OTP_DB_CREATE 0x02 /* create database? */
@ -135,6 +143,7 @@ struct otp_user {
uint16_t key_size; /* bytes used in key */
unsigned char key[OTP_USER_KEY_LEN]; /* shared key (may not all be used */
char username[OTP_USER_NAME_LEN+1]; /* name, null terminated */
char loc[OTP_USER_LOC_LEN+1]; /* location to send token */
char ascii_encoded[OTP_USER_ASCII_LEN+1]; /* null terminated */
/*
@ -142,17 +151,20 @@ struct otp_user {
* version:name:key:status:format:type:count_cur:count_ceil:last
* n encoding decoded size encoded size
* --------------------------------------
* version 1 ASCII HEX 8 bits 2 bytes + 1
* username 2 ASCII 32 bytes 1..32 bytes + 1
* key 3 ASCII HEX 20 bytes 40 bytes + 1
* status 4 ASCII HEX 8 bits 2 bytes + 1
* format 5 ASCII HEX 8 bits 2 bytes + 1
* type 6 ASCII HEX 8 bits 2 bytes + 1
* flags 7 ASCII HEX 8 bits 2 bytes + 1
* count_cur 8 ASCII HEX 64 bits 16 bytes + 1
* count_ceil 9 ASCII HEX 64 bits 16 bytes + 1
* last 10 ASCII HEX 64 bits 16 bytes + 1 null
* total bytes = 2+32+40+2+2+2+2_16+16+16+10 = 140
* version 1 ASCII HEX 8 bits 2 bytes
* username 2 ASCII 32 bytes 1..32 bytes
* key 3 ASCII HEX 20 bytes 40 bytes
* status 4 ASCII HEX 8 bits 2 bytes
* format 5 ASCII HEX 8 bits 2 bytes
* type 6 ASCII HEX 8 bits 2 bytes
* flags 7 ASCII HEX 8 bits 2 bytes
* count_cur 8 ASCII HEX 64 bits 16 bytes
* count_ceil 9 ASCII HEX 64 bits 16 bytes
* last 10 ASCII HEX 64 bits 16 bytes
* location 11 ASCII 40 bytes 1..40 bytes
* delimiters - 1 * (n-1) 10 bytes
* null - 1 byte
* total bytes = 2+32+40+2+2+2+2+16+16+16+40+10+1 = 181
*/
};
@ -160,6 +172,7 @@ struct otp_user {
struct otp_ctx {
struct ffdb_ctx *ffdbctx;
char *send_token_pathname;
int valid;
int verbose;
};
@ -180,13 +193,15 @@ int otp_db_dump(struct otp_ctx *otpctx, char *u_username);
int otp_db_load(struct otp_ctx *otpctx, char *u_username);
int otp_user_add(struct otp_ctx *otpctx, char *u_username,
uint8_t *u_key_val, uint16_t u_key_size, uint64_t u_count,
uint64_t u_count_ceil, uint8_t u_status, uint8_t u_type,
uint8_t u_format, uint8_t u_version);
char *u_loc, uint8_t *u_key_val, uint16_t u_key_size,
uint64_t u_count, uint64_t u_count_ceil, uint8_t u_status,
uint8_t u_type, uint8_t u_format, uint8_t u_version);
int otp_user_exists(struct otp_ctx *otpctx, char *u_username);
int otp_user_rm(struct otp_ctx *otpctx, char *u_username);
int otp_user_auth(struct otp_ctx *otpctx, char *u_username,
char *u_crsp, int u_window);
int otp_user_send_token(struct otp_ctx *otpctx, char *u_username,
char *service);
int otp_urec_open(struct otp_ctx *otpctx, char *u_username,
struct otp_user *ou, int open_flags, int op_flags);

View file

@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: str.c 87 2009-12-28 00:05:53Z maf $
* $Id: str.c 164 2011-05-11 03:57:41Z maf $
*/
#include <termios.h>
@ -279,6 +279,9 @@ int str_input(const char *prompt, char *buf, size_t buf_size, int flags)
t.c_lflag &= ~ECHO;
if (tcsetattr(STDIN_FILENO, TCSANOW, &t) < 0)
return -1;
}
printf("%s", prompt); fflush(stdout);
@ -326,6 +329,9 @@ str_input_out:
t.c_lflag |= ECHO;
if (tcsetattr(STDIN_FILENO, TCSANOW, &t) < 0)
return -1;
}
return ret;
@ -335,58 +341,106 @@ str_input_out:
/*
* function: str_safe
*
* Ensure length of string is not > len
* note n is the length of the string
* where n+1 bytes are required to store
* it with trailing null.
*
* Ensure string is limited to [a-zA-Z0-9.]
*
* First invalid character is set to 0.
*
* returns "safe" string
* see STR_SAFE_*
*
*/
int str_safe(char *input, size_t len)
int str_safe(char *input, size_t input_len_max, char *ok_set, int flags)
{
size_t n;
int ret;
size_t n, input_len, ok_len, s;
int ret, null_flag, ok_flag;
ret = 0; /* success */
n = strlen(input);
null_flag = 0;
for (input_len = 0; input_len <= input_len_max; ++input_len) {
if (input[input_len] == 0) {
null_flag = 1;
break;
}
/* bounds verification */
if (n > len) {
input[len] = 0;
ret = -1;
}
for (n = 0; n < len; ++n) {
if (flags & STR_SAFE_CHECK_LEN) {
/* a-z */
if ((input[n] >= 'a') && (input[n] <= 'z'))
continue;
if (!null_flag) {
/* A-Z */
if ((input[n] >= 'A') && (input[n] <= 'Z'))
continue;
if (flags & STR_SAFE_WARN)
xerr_warnx("%s: size overrun", __func__);
/* 0-9 */
if ((input[n] >= '0') && (input[n] <= '9'))
continue;
if (flags & STR_SAFE_FIX) {
/* . */
if (input[n] == '.')
continue;
input[input_len_max] = 0;
input_len = input_len_max;
/* unsafe */
}
input[n] = 0;
ret = -1;
break;
ret |= STR_SAFE_FAIL_LEN;
} /* for each byte in input */
}
} /* STR_SAFE_CHECK_LEN */
if (flags & (STR_SAFE_CHECK_ALPHA|STR_SAFE_CHECK_NUM|STR_SAFE_CHECK_SET)) {
for (n = 0; n < input_len; ++n) {
if (flags & STR_SAFE_CHECK_ALPHA) {
/* a-z */
if ((input[n] >= 'a') && (input[n] <= 'z'))
continue;
/* A-Z */
if ((input[n] >= 'A') && (input[n] <= 'Z'))
continue;
} /* STR_SAFE_CHECK_ALPHA */
if (flags & STR_SAFE_CHECK_NUM) {
/* 0-9 */
if ((input[n] >= '0') && (input[n] <= '9'))
continue;
} /* STR_SAFE_CHECK_NUM */
if (flags & STR_SAFE_CHECK_SET) {
ok_len = strlen(ok_set);
ok_flag = 0; /* bad */
for (s = 0; s < ok_len; ++s) {
if (input[n] == ok_set[s]) {
ok_flag = 1; /* good */
break;
}
} /* test char in ok_set */
if (ok_flag)
continue;
} /* STR_SAFE_CHECK_SET */
ret |= STR_SAFE_FAIL_CHAR;
/* unsafe */
if (flags & STR_SAFE_WARN)
xerr_warnx("%s: illegal char @ index=%d", __func__, n);
if (flags & STR_SAFE_FIX)
input[input_len] = '_';
} /* for each byte in input */
} /* STR_SAFE_CHECK_FNAME */
return ret;
@ -501,7 +555,6 @@ int str_setflag8(char *list[], uint8_t *flags, char *s, uint8_t min,
uint8_t max)
{
int i;
*flags = 0;
for (i = min; i < max; ++i) {
if (!strcasecmp(s, list[i]))

View file

@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: str.h 85 2009-12-28 00:05:02Z maf $
* $Id: str.h 154 2011-04-06 02:21:29Z maf $
*/
#include <sys/types.h>
@ -42,7 +42,7 @@ int str_hex_dump(char *buf, u_char *b, size_t n);
int str_hex_decode(char *in, size_t in_len, u_char *out, size_t out_len);
void str_ftoc(char *buf, char *f, size_t n);
int str_input(const char *prompt, char *buf, size_t buf_size, int flags);
int str_safe(char *input, size_t len);
int str_safe(char *input, size_t input_max_len, char *ok_set, int flags);
int str_uint32toa(char *s, uint32_t u);
char *str_lookup8(char *list[], uint8_t id, uint8_t min, uint8_t max);
@ -59,4 +59,14 @@ int str_find8(char *list[], uint8_t *id, char *s, uint8_t min, uint8_t max);
#define STR_UINT32_LEN 11 /* 2^32-1=4294967295 + NULL = 11 bytes */
#define STR_SAFE_CHECK_LEN 0x0001 /* length */
#define STR_SAFE_CHECK_ALPHA 0x0002 /* a-zA-Z */
#define STR_SAFE_CHECK_NUM 0x0004 /* 0-9 */
#define STR_SAFE_CHECK_FNAME 0x000E /* ALPHA+NUM+ .-_ */
#define STR_SAFE_CHECK_SET 0x0010 /* elements are all in char_set */
#define STR_SAFE_FIX 0x1000 /* fix problem string */
#define STR_SAFE_WARN 0x2000 /* enable warnings */
#define STR_SAFE_FAIL_CHAR 0x1
#define STR_SAFE_FAIL_LEN 0x2

BIN
doc/BCTutorial.pdf Normal file

Binary file not shown.

View file

@ -1,5 +1,54 @@
# $Id:$
urd/rc.d/urd: updated for new flags
otp-control: mode generate will honor -c
send-tokendd: reference implementation of OOB token. Sends token to web
page via ssl. Used internally for SMS gateway.
send-token feature. Send to token to user via flexible OOB method.
HOTPC.BAS rev 9. Check PIN, readerKey
otp-sca support SC_SETREADERKEY_CAP
pam_otp.so: require_db_entry is now defaulted to enabled. A new option
allow_unknown_user which is mutually exclusive to require_db_entry is
accepted for consistency with urd and openvpn. kyriacou@osc.edu
otpdb2sc missing quote. kyriacou@osc.edu
openvpn plugin accepts otp-allow-unknown-user
otp-control will by default create a new user with count=1. BasicCard
code treats count=0 as a special case when a challenge (count) is supplied.
0 is ignore challenge and use EEPROM stored count.
getopt_long() support. All binaries support --version.
honor OTP_FLAGS_DISPNT in urd. Use -c to force display
urd will omit password when packed decode debug is enabled
fix state hex encoding in urd when state > 127
fix soft reload option in urd
add PAM password authentication to urd
str.c: tcsetattr() missing in str_input()
otp-control -m list-sc will automatically set the correct FMT flags
document behavior of count=0 in otp-sct, otp-sca, and spyrus-reader
add urd/rc.d script to dist
add rfc.card to dist
spyrus1.4.hex installed instead of 1.3. Also in QUICKSTART
### ootp-1.03.tar.gz
add CHANGES and TODO to dist

View file

@ -1,4 +1,4 @@
# $Id: Makefile 13 2009-11-26 16:37:03Z maf $
# $Id: Makefile 153 2011-04-01 02:38:36Z maf $
INSTALL=install -c -m0644
@ -16,7 +16,7 @@ MISCDIR=/usr/local/ootp/doc
docbook-to-man $*.sgml > $@
.sgml.html:
openjade -V nochunks -c /usr/local/share/sgml/docbook/dsssl/modular/catalog -c /usr/local/share/sgml/docbook/catalog -c /usr/local/share/sgml/jade/catalog -d /usr/local/share/sgml/docbook/dsssl/modular/html/docbook.dsl -t sgml $*.sgml > $*.html
openjade -V nochunks -c /usr/local/share/sgml/docbook/dsssl/modular/catalog -c /usr/local/share/sgml/docbook/3.1/dtd/catalog -c /usr/local/share/sgml/jade/catalog -d /usr/local/share/sgml/docbook/dsssl/modular/html/docbook.dsl -t sgml $*.sgml > $*.html
MAN1S = htsoft-downloader.1 bcload.1 otp-control.1 otp-ov-plugin.1\
pam_otp.1 urd.1 otp-sca.1 otp-sct.1

View file

@ -1,5 +1,5 @@
#
# $Id: QUICKSTART 76 2009-12-26 21:04:01Z maf $
# $Id: QUICKSTART 114 2010-02-25 18:23:44Z maf $
#
OpenOTP is an implementation of the HOTP protocol using a ZeitControl
@ -326,7 +326,7 @@ semanage fcontext -a -t textrel_shlib_t /lib/security/pam_otp.so
# create the OTP database with one inactive user (joe)
otp-control -n -u joe -m add
otp-control -u joe -m set-status inactive
otp-control -u joe -m set-status -s inactive
otp-control -u joe -m list
>Username.......joe
@ -408,7 +408,7 @@ Last login: Wed Sep 2 00:22:03 2009 from 10.1.0.26
#### Downloading firmware to the Spyrus reader
The Spyrus PAR II will be programmed with the spyrus1.3.hex application
The Spyrus PAR II will be programmed with the spyrus1.4.hex application
included in the OTP distribution. This will be done once per new reader,
or when new application software is required. An proprietary RS232 serial
programming cable available from Spyrus is needed.
@ -425,10 +425,10 @@ arrow until the "DownloadApp" menu item is present.
Start the htsoft-downloader utility using serial port at /dev/cuaU0 :
# FreeBSD USB Serial Adapter
htsoft-downloader -v1 -i -f /dev/cuaU0 < $OOTP/firmware/spyrus1.3.hex
htsoft-downloader -v1 -i -f /dev/cuaU0 < $OOTP/firmware/spyrus1.4.hex
# Linux USB Serial Adapter
htsoft-downloader -v1 -i -f /dev/ttyS0 < $OOTP/firmware/spyrus1.3.hex
htsoft-downloader -v1 -i -f /dev/ttyS0 < $OOTP/firmware/spyrus1.4.hex
Press Enter on the spyrus reader to start the download application:

BIN
doc/REF_ACx30.pdf Normal file

Binary file not shown.

View file

@ -1,7 +1,18 @@
autoconf/automake
urd option c should not require arg
urd_oareng_pgm support in rc.d
urd opt n should include character list
man page for option n
RADIUS optionally encode HOTP count in challenge message
RADIUS dspcnt flag urd, force display count
tokend
man page
usage
urd,openvpn
send-token
Enter PIN code does not issue a \n
autoconf/automake
RADIUS proxy support
@ -10,17 +21,12 @@ ACS balance reader support dec31.6?
break out htsoft-downloader, urd, bcload?
architecture document
formats
post
basiccard build notes
full coverage testing for otplib and ffdb
otp-token (soft token)
count use 64 bit current time option
count use 64 bit current time option, store last time delta for each user to
help compensate for reader drift.
balance reader simulator
@ -33,3 +39,16 @@ Spyrus main.c missing
U8 Temp[4];
RESP_INFO *respDump = (RESP_INFO*) Temp;
-S in otp-control - use symbolic names
option in otp-sca to list symbolic names of flags
otp-sca
make sure d modifier still works
tail -1 in otp-control example
use RFC keys for examples
urd - wtmp
otp-control -c should do the right thing when generating otp

BIN
doc/balanceR.pdf Normal file

Binary file not shown.

View file

@ -66,19 +66,19 @@ off the bcload example included in the development environment\&.
hardware\&. Small changes would be required to support the Professional
line of cards\&.
.SH "OPTIONS"
.IP "-d\fI debug_level\fP" 10
.IP "-d, --debug=\fI debug_level\fP" 10
Set debug level\&.
.IP "-f\fI fname\fP" 10
.IP "-f, --image=\fI fname\fP" 10
Name of BasicCard Image file\&. Defaults to HOTPC\&.IMG
.IP "-h" 10
.IP "-h, --help" 10
Help\&.
.IP "-l" 10
.IP "-l, --list-readers" 10
List SC Readers
.IP "-p" 10
.IP "-p, --no-paranoid" 10
Disable paranoid check for ZC3\&.9 hardware\&. Enhanced Smart Cards will
probably work, support for the professional cards require changes
to \fBbcload\&.c\fP\&.
.IP "-r\fI reader\fP" 10
.IP "-r, --reader=\fI reader\fP" 10
Set Smart Card reader\&. Use -l to list available readers\&. A reader
is defined as class:reader:[option]\&. PCSC and embedded
are the two available classes\&. The embedded class contains the acr30s driver
@ -87,11 +87,13 @@ If pcscd is running the first PC/SC reader will be the default followed by
the embedded acr30s driver\&. Use PCSC: for the first available PC/SC
reader\&. Use embedded:acr30s:/dev/cuaU0 for the embedded acr30s driver
with serial port /dev/cuaU0\&.
.IP "-t" 10
.IP "-t, --force-test" 10
Force card mode to TEST after programming\&. Defaults to the mode
specified in the image file\&.
.IP "-v" 10
.IP "-v, --verbose" 10
Display verbose status messages while programming the card\&.
.IP "--version" 10
Display software version\&.
.SH "EXAMPLES"
.PP
Download the HOTPC\&.IMG file to the default Smart Card reader\&. Display
@ -134,4 +136,4 @@ Mark Fullmer maf@splintered\&.net
\fBotp-ov-plugin\fP(1)
\fBurd\fP(1)
spyrus-par2(7)
...\" created by instant / docbook-to-man, Sun 27 Dec 2009, 22:01
...\" created by instant / docbook-to-man, Sun 15 May 2011, 23:57

View file

@ -97,7 +97,7 @@ NAME="AEN26"
CLASS="VARIABLELIST"
><DL
><DT
>-d<TT
>-d, --debug=<TT
CLASS="REPLACEABLE"
><I
> debug_level</I
@ -108,7 +108,7 @@ CLASS="REPLACEABLE"
>Set debug level.</P
></DD
><DT
>-f<TT
>-f, --image=<TT
CLASS="REPLACEABLE"
><I
> fname</I
@ -119,19 +119,19 @@ CLASS="REPLACEABLE"
>Name of BasicCard Image file. Defaults to HOTPC.IMG</P
></DD
><DT
>-h</DT
>-h, --help</DT
><DD
><P
>Help.</P
></DD
><DT
>-l</DT
>-l, --list-readers</DT
><DD
><P
>List SC Readers</P
></DD
><DT
>-p</DT
>-p, --no-paranoid</DT
><DD
><P
>Disable paranoid check for ZC3.9 hardware. Enhanced Smart Cards will
@ -142,7 +142,7 @@ CLASS="FILENAME"
>.</P
></DD
><DT
>-r<TT
>-r, --reader=<TT
CLASS="REPLACEABLE"
><I
> reader</I
@ -166,25 +166,31 @@ reader. Use embedded:acr30s:/dev/cuaU0 for the embedded acr30s driver
with serial port /dev/cuaU0.</P
></DD
><DT
>-t</DT
>-t, --force-test</DT
><DD
><P
>Force card mode to TEST after programming. Defaults to the mode
specified in the image file.</P
></DD
><DT
>-v</DT
>-v, --verbose</DT
><DD
><P
>Display verbose status messages while programming the card.</P
></DD
><DT
>--version</DT
><DD
><P
>Display software version.</P
></DD
></DL
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AEN67"
NAME="AEN71"
></A
><H2
>EXAMPLES</H2
@ -193,7 +199,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN69"
NAME="AEN73"
></A
><P
>Download the HOTPC.IMG file to the default Smart Card reader. Display
@ -236,7 +242,7 @@ BCSetState: test</SAMP
><DIV
CLASS="REFSECT1"
><A
NAME="AEN74"
NAME="AEN78"
></A
><H2
>AUTHOR</H2
@ -253,7 +259,7 @@ HREF="mailto:maf@splintered.net"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN81"
NAME="AEN85"
></A
><H2
>SEE ALSO</H2

View file

@ -1,6 +1,6 @@
<!DOCTYPE refentry PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
<!-- $Id: bcload.sgml 62 2009-12-18 17:26:31Z maf $ -->
<!-- $Id: bcload.sgml 126 2010-06-15 14:23:02Z maf $ -->
<refentry>
<refmeta>
@ -45,7 +45,7 @@ line of cards.
<variablelist>
<varlistentry>
<term>-d<replaceable> debug_level</replaceable></term>
<term>-d, --debug=<replaceable> debug_level</replaceable></term>
<listitem>
<para>
Set debug level.
@ -54,7 +54,7 @@ Set debug level.
</varlistentry>
<varlistentry>
<term>-f<replaceable> fname</replaceable></term>
<term>-f, --image=<replaceable> fname</replaceable></term>
<listitem>
<para>
Name of BasicCard Image file. Defaults to HOTPC.IMG
@ -63,7 +63,7 @@ Name of BasicCard Image file. Defaults to HOTPC.IMG
</varlistentry>
<varlistentry>
<term>-h</term>
<term>-h, --help</term>
<listitem>
<para>
Help.
@ -72,7 +72,7 @@ Help.
</varlistentry>
<varlistentry>
<term>-l</term>
<term>-l, --list-readers</term>
<listitem>
<para>
List SC Readers
@ -81,7 +81,7 @@ List SC Readers
</varlistentry>
<varlistentry>
<term>-p</term>
<term>-p, --no-paranoid</term>
<listitem>
<para>
Disable paranoid check for ZC3.9 hardware. Enhanced Smart Cards will
@ -92,7 +92,7 @@ to <filename>bcload.c</filename>.
</varlistentry>
<varlistentry>
<term>-r<replaceable> reader</replaceable></term>
<term>-r, --reader=<replaceable> reader</replaceable></term>
<listitem>
<para>
Set Smart Card reader. Use -l to list available readers. A reader
@ -108,7 +108,7 @@ with serial port /dev/cuaU0.
</varlistentry>
<varlistentry>
<term>-t</term>
<term>-t, --force-test</term>
<listitem>
<para>
Force card mode to TEST after programming. Defaults to the mode
@ -118,7 +118,7 @@ specified in the image file.
</varlistentry>
<varlistentry>
<term>-v</term>
<term>-v, --verbose</term>
<listitem>
<para>
Display verbose status messages while programming the card.
@ -126,6 +126,14 @@ Display verbose status messages while programming the card.
</listitem>
</varlistentry>
<varlistentry>
<term>--version</term>
<listitem>
<para>
Display software version.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View file

@ -67,11 +67,7 @@ file from picc, MPLAB, gpasm, or other PIC compatible toolchains) is read
on standard output and downloaded to a PIC on the
\fIserial_device\fP\&.
.SH "OPTIONS"
.IP "-h" 10
Help
.IP "-i" 10
Ignore timeout for last WOK after sending reset\&.
.IP "-f\fI serial_device\fP" 10
.IP "-f, --serial-device=\fI serial_device\fP" 10
Serial device filename\&. Examples:
.IP "" 10
\fB/dev/ttyUSB0\fP (Linux USB Serial Adapter)
@ -80,14 +76,20 @@ Serial device filename\&. Examples:
.IP "" 10
The default is \fB/dev/cuaU0\fP, a
Prolific PL2303 USB to serial adaptor on FreeBSD\&.
.IP "-r\fI retries\fP" 10
.IP "-h, --help" 10
Help
.IP "-i, --ignore-last-wok-timeout" 10
Ignore timeout for last WOK after sending reset\&.
.IP "-r, --pic-retries=\fI retries\fP" 10
Number of times to retry a block\&. Defaults to 5\&.
.IP "-t\fI timeout\fP" 10
.IP "-t, --pic-timeout=\fI timeout\fP" 10
Timeout in \&.1 second intervals\&. Defaults to 25\&.
.IP "-v\fI verbose_level\fP" 10
.IP "-v, --verbose=\fI verbose_level\fP" 10
Increasing the verbosity level will produce debug messages indicating
the status of the download\&. A level of 9 will include all debugging
output\&. A level of 1 will indicate the overall status of the transfer\&.
.IP "--version" 10
Display software version\&.
.SH "EXAMPLE"
.PP
Transfer the HEX file spyrus1\&.1\&.hex to a PIC connected to
@ -125,4 +127,4 @@ Intel Hexadecimal Object File Format Specification Rev A
www\&.htsoft\&.com
.PP
http://www\&.ehl\&.cz/pic/pic_e\&.htm
...\" created by instant / docbook-to-man, Sun 27 Dec 2009, 22:01
...\" created by instant / docbook-to-man, Sun 15 May 2011, 23:57

View file

@ -102,19 +102,7 @@ NAME="AEN27"
CLASS="VARIABLELIST"
><DL
><DT
>-h</DT
><DD
><P
>Help</P
></DD
><DT
>-i</DT
><DD
><P
>Ignore timeout for last WOK after sending reset.</P
></DD
><DT
>-f<TT
>-f, --serial-device=<TT
CLASS="REPLACEABLE"
><I
> serial_device</I
@ -141,7 +129,19 @@ CLASS="FILENAME"
Prolific PL2303 USB to serial adaptor on FreeBSD.</P
></DD
><DT
>-r<TT
>-h, --help</DT
><DD
><P
>Help</P
></DD
><DT
>-i, --ignore-last-wok-timeout</DT
><DD
><P
>Ignore timeout for last WOK after sending reset.</P
></DD
><DT
>-r, --pic-retries=<TT
CLASS="REPLACEABLE"
><I
> retries</I
@ -152,7 +152,7 @@ CLASS="REPLACEABLE"
>Number of times to retry a block. Defaults to 5.</P
></DD
><DT
>-t<TT
>-t, --pic-timeout=<TT
CLASS="REPLACEABLE"
><I
> timeout</I
@ -163,7 +163,7 @@ CLASS="REPLACEABLE"
>Timeout in .1 second intervals. Defaults to 25.</P
></DD
><DT
>-v<TT
>-v, --verbose=<TT
CLASS="REPLACEABLE"
><I
> verbose_level</I
@ -175,13 +175,19 @@ CLASS="REPLACEABLE"
the status of the download. A level of 9 will include all debugging
output. A level of 1 will indicate the overall status of the transfer.</P
></DD
><DT
>--version</DT
><DD
><P
>Display software version.</P
></DD
></DL
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AEN64"
NAME="AEN68"
></A
><H2
>EXAMPLE</H2
@ -190,7 +196,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN66"
NAME="AEN70"
></A
><P
>Transfer the HEX file spyrus1.1.hex to a PIC connected to
@ -230,7 +236,7 @@ wDONE: reply=F0, expecting E4wPIC reset sent.</PRE
><DIV
CLASS="REFSECT1"
><A
NAME="AEN72"
NAME="AEN76"
></A
><H2
>AUTHOR</H2
@ -247,7 +253,7 @@ HREF="mailto:maf@splintered.net"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN79"
NAME="AEN83"
></A
><H2
>SEE ALSO</H2

View file

@ -1,6 +1,6 @@
<!DOCTYPE refentry PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
<!-- $Id: htsoft-downloader.sgml 74 2009-12-26 20:40:57Z maf $ -->
<!-- $Id: htsoft-downloader.sgml 126 2010-06-15 14:23:02Z maf $ -->
<refentry>
@ -50,25 +50,7 @@ on standard output and downloaded to a PIC on the
<variablelist>
<varlistentry>
<term>-h</term>
<listitem>
<para>
Help
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-i</term>
<listitem>
<para>
Ignore timeout for last WOK after sending reset.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-f<replaceable> serial_device</replaceable></term>
<term>-f, --serial-device=<replaceable> serial_device</replaceable></term>
<listitem>
<para>
Serial device filename. Examples:
@ -87,7 +69,25 @@ Prolific PL2303 USB to serial adaptor on FreeBSD.
</varlistentry>
<varlistentry>
<term>-r<replaceable> retries</replaceable></term>
<term>-h, --help</term>
<listitem>
<para>
Help
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-i, --ignore-last-wok-timeout</term>
<listitem>
<para>
Ignore timeout for last WOK after sending reset.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-r, --pic-retries=<replaceable> retries</replaceable></term>
<listitem>
<para>
Number of times to retry a block. Defaults to 5.
@ -96,7 +96,7 @@ Number of times to retry a block. Defaults to 5.
</varlistentry>
<varlistentry>
<term>-t<replaceable> timeout</replaceable></term>
<term>-t, --pic-timeout=<replaceable> timeout</replaceable></term>
<listitem>
<para>
Timeout in .1 second intervals. Defaults to 25.
@ -105,7 +105,7 @@ Timeout in .1 second intervals. Defaults to 25.
</varlistentry>
<varlistentry>
<term>-v<replaceable> verbose_level</replaceable></term>
<term>-v, --verbose=<replaceable> verbose_level</replaceable></term>
<listitem>
<para>
Increasing the verbosity level will produce debug messages indicating
@ -115,6 +115,15 @@ output. A level of 1 will indicate the overall status of the transfer.
</listitem>
</varlistentry>
<varlistentry>
<term>--version</term>
<listitem>
<para>
Display software version.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

BIN
doc/ootp-arch-overview.pdf Normal file

Binary file not shown.

View file

@ -56,16 +56,16 @@
\fBotp-control\fP \(em Local user database configuration for One Time Password package\&.
.SH "SYNOPSIS"
.PP
\fBotp-control\fP [-?hnv] [-c\fI count\fP] [-C\fI count_ceil\fP] [-f\fI format\fP] [-F\fI flags\fP] [-H\fI sc_hostname\fP] [-I\fI sc_index\fP] [-k\fI key\fP] [-m\fI command_mode\fP] [-o\fI otpdb_pathname\fP] [-s\fI status\fP] [-S\fI sc_flags\fP] [-t\fI type\fP] [-u\fI username\fP] [-w\fI window\fP]
\fBotp-control\fP [-?hnv] [-c\fI count\fP] [-C\fI count_ceiling\fP] [-f\fI format\fP] [-F\fI flag\fP] [-H\fI sc_hostname\fP] [-I\fI sc_index\fP] [-k\fI key\fP] [-l\fI location\fP] [-m\fI command_mode\fP] [-o\fI otp_db\fP] [-s\fI status\fP] [-S\fI sc_flags\fP] [-t\fI type\fP] [-u\fI username\fP] [-V\fI service_name\fP] [-w\fI window\fP]
.SH "DESCRIPTION"
.PP
The \fBotp-control\fP command is a front end to the
local One Time Password database\&. Users can be added, modified
and removed by \fBotp-control\&.\fP
.SH "OPTIONS"
.IP "-c\fI count\fP" 10
.IP "-c, --count= \fI count\fP" 10
User count\&. The count increases with each OTP transaction\&.
.IP "-C\fI count_ceil\fP" 10
.IP "-C, --count-ceil= \fI count_ceiling\fP" 10
User count ceiling\&. Highest count allowed for this user\&. Configuring
the count_ceiling allows a user key to be shared among multiple
systems each with a unique count window, where count <= count_ceiling\&.
@ -74,9 +74,9 @@ A count value must only be allowed for authentication once\&.
.IP "" 10
Example:
.IP "" 10
host=h1, user=bob, count_current=0, count_ceil=10000\&.
host=h1, user=bob, count_current=0, count_ceiling=10000\&.
.IP "" 10
host=h2, user=bob, count_current=10001, count_ceil=20000\&.
host=h2, user=bob, count_current=10001, count_ceiling=20000\&.
.IP "" 10
The number of keys a user must possess is decreased at the expense
of security dependencies among multiple systems\&. If system A is
@ -86,34 +86,37 @@ must be presented to the OTP generator\&. The additional step of entering
the count to the OTP generator is not necessary when keys are not
shared, as the currrent count will increase on the OTP generator and
system database during authentication\&.
.IP "-f" 10
.IP "-f, --format=" 10
OTP format\&. One of hex40 dhex40 dec31\&.6 dec31\&.7 dec31\&.8 dec31\&.9 dec31\&.10\&.
hex40 (40 bit hex) is the default\&. dec31\&.6 (31 bit decimal truncated to 6
digits) is suggested by RFC 4226 and may be required to interoperate with
other HOTP implementations\&. dhex40 uses the dynamic truncate function
in RFC 4226, where hex40 always uses the top 40 bits\&. dhex40 may be the
default in future releases\&.
.IP "-F" 10
OTP flags\&. All flags are unset by default\&.
.IP "-F, --flag=" 10
OTP flag\&. All flags are unset by default\&.
.PP
.nf
Flag Description
-----------------------------------------------------------------
display-count : Display HOTP count when prompted for challenge\&.
send-token : Send token to user out of band\&.
.fi
.IP "-h" 10
.IP "-h, --help" 10
Help\&.
.IP "-H\fI sc_hostname\fP" 10
Set the SC hostname with the list-sc command mode\&.
.IP "-I\fI sc_index\fP" 10
Set the SC index with the list-sc command mode\&.
.IP "-k\fI key\fP" 10
.IP "-H, --sc_hostname=\fI sc_hostname\fP" 10
Set the SC hostname for the list-sc command mode\&.
.IP "-I, --sc_index=\fI sc_index\fP" 10
Set the SC index for the list-sc command mode\&.
.IP "-k, --key=\fI key\fP" 10
160 bit shared secret key in ASCII HEX\&. The secret key is shared between
the OTP generation hardware/software for a user and the local OTP database\&.
Each user typically will have a unique key unless a shared key with
unique count space is provisioned\&. Use - for stdin\&. Example key:
C0C3D47F1CC68ECE0DF81D008F0C0D72D43EB745
.IP "-m\fI command_mode\fP" 10
.IP "-l, --location=\fI location\fP" 10
Location to send token to when SEND_TOKEN flag is set\&.
.IP "-m, --command_mode=\fI command_mode\fP" 10
.PP
.nf
Mode Description
@ -126,6 +129,7 @@ C0C3D47F1CC68ECE0DF81D008F0C0D72D43EB745
list-sc - List user record (SC friendly)
load - ASCII load user record(s)
remove - Remove user
send-token - Send token to user
set-count - Set user count
set-count-ceil - Set user count ceiling
set-flags - Set user flags
@ -134,11 +138,11 @@ C0C3D47F1CC68ECE0DF81D008F0C0D72D43EB745
set-type - Set user OTP type
test - Test user
.fi
.IP "-n" 10
.IP "-n, --create_database" 10
Create new database if one does not exist\&.
.IP "-o\fI otp_pathname\fP" 10
.IP "-o, --otp-db=\fI otp_db\fP" 10
Pathname of OTP database\&.
.IP "-s\fI otp_pathname\fP" 10
.IP "-s, --status=\fI status\fP" 10
OTP Status\&. The default status is active\&.
.PP
.nf
@ -148,18 +152,23 @@ OTP Status\&. The default status is active\&.
inactive : OTP may not be required for successful authentication\&.
The OTP authentication module may be configured to allow
inactive accounts to authenticate\&. This may be used to
temporarily remove the OTP authentication method for a user\&.
temporarily remove the OTP authentication method for a
user\&.
disabled : Account is disabled\&. OTP authentication will fail\&.
.fi
.IP "-S\fI sc_flags\fP" 10
Set the SC flags with the list-sc command mode\&. 0=CHALLENGE, 1=READERKEY\&.
.IP "-t\fI type\fP" 10
.IP "-S, --sc-flags=\fI sc_flags\fP" 10
Set the SC flags for the list-sc command mode\&. 0=CHALLENGE, 1=READERKEY\&.
.IP "-t, --type=\fI type\fP" 10
OTP Type\&. RFC 4226 HOTP is only supported type\&.
.IP "-u\fI username\fP" 10
.IP "-u, --username=\fI username\fP" 10
Username to perform database operation on\&.
.IP "-v" 10
.IP "-v, --verbose" 10
Enable verbose output (debugging)\&.
.IP "-w\fI window\fP" 10
.IP "-V, --service-name=\fI service_name\fP" 10
Set service name for send-token function\&.
.IP "--version" 10
Display software version\&.
.IP "-w, --challenge-window=\fI window\fP" 10
Set the maximum window (count above the system count) where an OTP
will successfully authenticate\&. For user bob with with OTP generator
count_current=30, and system OTP database for bob count_current 15, the
@ -182,7 +191,7 @@ user stored in a separate ASCII : delimited file in base_dir/d\&.
\fBdump\fP : dump user database in ASCII\&. User records are separated by a newline\&.
Fields are : separated\&. All fields except the username are HEX encoded\&.
.PP
#version:user:key:status:format:type:flags:count_cur:count_ceil:last
#version:user:key:status:format:type:flags:count_cur:count_ceiling:last
01:test:1111111111111111111111111111111111111111:01:01:01:00:00000000000003E8:00000000000007D0:0000000000000000
.PP
\fBgenerate\fP : generate OTP for user\&. The -w flag may be used to generate multiple
@ -263,7 +272,7 @@ Use the load command to import records in this format\&.
\fBotp-control -m dump\fP
.PP
.nf
#version:user:key:status:format:type:flags:count_cur:count_ceil:last
#version:user:key:status:format:type:flags:count_cur:count_ceiling:last
01:bob:C381739834A63A67B0B9F7F7D36C8C567F6BFB3D:01:01:01:00:0000000000000001:FFFFFFFFFFFFFFFF:000000004AA02F9E
.fi
.PP
@ -290,4 +299,4 @@ Mark Fullmer maf@splintered\&.net
\fBurd\fP(1)
\fBbcload\fP(1)
spyrus-par2(7)
...\" created by instant / docbook-to-man, Sun 27 Dec 2009, 22:01
...\" created by instant / docbook-to-man, Sun 15 May 2011, 23:57

View file

@ -51,7 +51,7 @@ CLASS="REPLACEABLE"
>] [-C<TT
CLASS="REPLACEABLE"
><I
> count_ceil</I
> count_ceiling</I
></TT
>] [-f<TT
CLASS="REPLACEABLE"
@ -61,7 +61,7 @@ CLASS="REPLACEABLE"
>] [-F<TT
CLASS="REPLACEABLE"
><I
> flags</I
> flag</I
></TT
>] [-H<TT
CLASS="REPLACEABLE"
@ -78,6 +78,11 @@ CLASS="REPLACEABLE"
><I
> key</I
></TT
>] [-l<TT
CLASS="REPLACEABLE"
><I
> location</I
></TT
>] [-m<TT
CLASS="REPLACEABLE"
><I
@ -86,7 +91,7 @@ CLASS="REPLACEABLE"
>] [-o<TT
CLASS="REPLACEABLE"
><I
> otpdb_pathname</I
> otp_db</I
></TT
>] [-s<TT
CLASS="REPLACEABLE"
@ -108,6 +113,11 @@ CLASS="REPLACEABLE"
><I
> username</I
></TT
>] [-V<TT
CLASS="REPLACEABLE"
><I
> service_name</I
></TT
>] [-w<TT
CLASS="REPLACEABLE"
><I
@ -118,7 +128,7 @@ CLASS="REPLACEABLE"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN42"
NAME="AEN46"
></A
><H2
>DESCRIPTION</H2
@ -136,7 +146,7 @@ CLASS="COMMAND"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN47"
NAME="AEN51"
></A
><H2
>OPTIONS</H2
@ -146,7 +156,7 @@ NAME="AEN47"
CLASS="VARIABLELIST"
><DL
><DT
>-c<TT
>-c, --count= <TT
CLASS="REPLACEABLE"
><I
> count</I
@ -157,10 +167,10 @@ CLASS="REPLACEABLE"
>User count. The count increases with each OTP transaction.</P
></DD
><DT
>-C<TT
>-C, --count-ceil= <TT
CLASS="REPLACEABLE"
><I
> count_ceil</I
> count_ceiling</I
></TT
></DT
><DD
@ -173,9 +183,9 @@ systems each with a unique count window, where count &#60;= count_ceiling.</P
><P
>Example:</P
><P
>host=h1, user=bob, count_current=0, count_ceil=10000.</P
>host=h1, user=bob, count_current=0, count_ceiling=10000.</P
><P
>host=h2, user=bob, count_current=10001, count_ceil=20000.</P
>host=h2, user=bob, count_current=10001, count_ceiling=20000.</P
><P
>The number of keys a user must possess is decreased at the expense
of security dependencies among multiple systems. If system A is
@ -187,7 +197,7 @@ shared, as the currrent count will increase on the OTP generator and
system database during authentication.</P
></DD
><DT
>-f</DT
>-f, --format=</DT
><DD
><P
>OTP format. One of hex40 dhex40 dec31.6 dec31.7 dec31.8 dec31.9 dec31.10.
@ -198,25 +208,26 @@ in RFC 4226, where hex40 always uses the top 40 bits. dhex40 may be the
default in future releases.</P
></DD
><DT
>-F</DT
>-F, --flag=</DT
><DD
><P
>OTP flags. All flags are unset by default.
>OTP flag. All flags are unset by default.
<PRE
CLASS="SCREEN"
> Flag Description
-----------------------------------------------------------------
display-count : Display HOTP count when prompted for challenge.</PRE
display-count : Display HOTP count when prompted for challenge.
send-token : Send token to user out of band.</PRE
></P
></DD
><DT
>-h</DT
>-h, --help</DT
><DD
><P
>Help.</P
></DD
><DT
>-H<TT
>-H, --sc_hostname=<TT
CLASS="REPLACEABLE"
><I
> sc_hostname</I
@ -224,10 +235,10 @@ CLASS="REPLACEABLE"
></DT
><DD
><P
>Set the SC hostname with the list-sc command mode.</P
>Set the SC hostname for the list-sc command mode.</P
></DD
><DT
>-I<TT
>-I, --sc_index=<TT
CLASS="REPLACEABLE"
><I
> sc_index</I
@ -235,10 +246,10 @@ CLASS="REPLACEABLE"
></DT
><DD
><P
>Set the SC index with the list-sc command mode.</P
>Set the SC index for the list-sc command mode.</P
></DD
><DT
>-k<TT
>-k, --key=<TT
CLASS="REPLACEABLE"
><I
> key</I
@ -253,7 +264,18 @@ unique count space is provisioned. Use - for stdin. Example key:
C0C3D47F1CC68ECE0DF81D008F0C0D72D43EB745</P
></DD
><DT
>-m<TT
>-l, --location=<TT
CLASS="REPLACEABLE"
><I
> location</I
></TT
></DT
><DD
><P
>Location to send token to when SEND_TOKEN flag is set.</P
></DD
><DT
>-m, --command_mode=<TT
CLASS="REPLACEABLE"
><I
> command_mode</I
@ -274,6 +296,7 @@ CLASS="SCREEN"
list-sc - List user record (SC friendly)
load - ASCII load user record(s)
remove - Remove user
send-token - Send token to user
set-count - Set user count
set-count-ceil - Set user count ceiling
set-flags - Set user flags
@ -283,16 +306,16 @@ CLASS="SCREEN"
test - Test user</PRE
></DD
><DT
>-n</DT
>-n, --create_database</DT
><DD
><P
>Create new database if one does not exist.</P
></DD
><DT
>-o<TT
>-o, --otp-db=<TT
CLASS="REPLACEABLE"
><I
> otp_pathname</I
> otp_db</I
></TT
></DT
><DD
@ -300,10 +323,10 @@ CLASS="REPLACEABLE"
>Pathname of OTP database.</P
></DD
><DT
>-s<TT
>-s, --status=<TT
CLASS="REPLACEABLE"
><I
> otp_pathname</I
> status</I
></TT
></DT
><DD
@ -317,12 +340,13 @@ CLASS="SCREEN"
inactive : OTP may not be required for successful authentication.
The OTP authentication module may be configured to allow
inactive accounts to authenticate. This may be used to
temporarily remove the OTP authentication method for a user.
temporarily remove the OTP authentication method for a
user.
disabled : Account is disabled. OTP authentication will fail.</PRE
></P
></DD
><DT
>-S<TT
>-S, --sc-flags=<TT
CLASS="REPLACEABLE"
><I
> sc_flags</I
@ -330,10 +354,10 @@ CLASS="REPLACEABLE"
></DT
><DD
><P
>Set the SC flags with the list-sc command mode. 0=CHALLENGE, 1=READERKEY.</P
>Set the SC flags for the list-sc command mode. 0=CHALLENGE, 1=READERKEY.</P
></DD
><DT
>-t<TT
>-t, --type=<TT
CLASS="REPLACEABLE"
><I
> type</I
@ -344,7 +368,7 @@ CLASS="REPLACEABLE"
>OTP Type. RFC 4226 HOTP is only supported type.</P
></DD
><DT
>-u<TT
>-u, --username=<TT
CLASS="REPLACEABLE"
><I
> username</I
@ -355,13 +379,30 @@ CLASS="REPLACEABLE"
>Username to perform database operation on.</P
></DD
><DT
>-v</DT
>-v, --verbose</DT
><DD
><P
>Enable verbose output (debugging).</P
></DD
><DT
>-w<TT
>-V, --service-name=<TT
CLASS="REPLACEABLE"
><I
> service_name</I
></TT
></DT
><DD
><P
>Set service name for send-token function.</P
></DD
><DT
>--version</DT
><DD
><P
>Display software version.</P
></DD
><DT
>-w, --challenge-window=<TT
CLASS="REPLACEABLE"
><I
> window</I
@ -385,7 +426,7 @@ of tokens generated.</P
><DIV
CLASS="REFSECT1"
><A
NAME="AEN139"
NAME="AEN157"
></A
><H2
>OTP-CONTROL COMMANDS</H2
@ -413,7 +454,7 @@ CLASS="COMMAND"
: dump user database in ASCII. User records are separated by a newline.
Fields are : separated. All fields except the username are HEX encoded.</P
><P
>#version:user:key:status:format:type:flags:count_cur:count_ceil:last
>#version:user:key:status:format:type:flags:count_cur:count_ceiling:last
01:test:1111111111111111111111111111111111111111:01:01:01:00:00000000000003E8:00000000000007D0:0000000000000000</P
><P
><B
@ -495,7 +536,7 @@ CLASS="COMMAND"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN172"
NAME="AEN190"
></A
><H2
>EXAMPLES</H2
@ -504,7 +545,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN174"
NAME="AEN192"
></A
><P
>Create a new OTP database /etc/otpdb. Add user bob with random key.</P
@ -525,7 +566,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN179"
NAME="AEN197"
></A
><P
>Display user bob OTP database entry.</P
@ -553,7 +594,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN184"
NAME="AEN202"
></A
><P
>Generate OTP for user bob.</P
@ -573,7 +614,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN189"
NAME="AEN207"
></A
><P
>Test OTP for user bob.</P
@ -595,7 +636,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN194"
NAME="AEN212"
></A
><P
>Dump OTP database to stdout. Fields other than username are hex encoded.
@ -607,7 +648,7 @@ CLASS="COMMAND"
></P
><PRE
CLASS="SCREEN"
>#version:user:key:status:format:type:flags:count_cur:count_ceil:last
>#version:user:key:status:format:type:flags:count_cur:count_ceiling:last
01:bob:C381739834A63A67B0B9F7F7D36C8C567F6BFB3D:01:01:01:00:0000000000000001:FFFFFFFFFFFFFFFF:000000004AA02F9E</PRE
><P
></P
@ -617,7 +658,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN199"
NAME="AEN217"
></A
><P
>Dump OTP user to stdout in format friendly to <B
@ -645,7 +686,7 @@ CLASS="COMPUTEROUTPUT"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN206"
NAME="AEN224"
></A
><H2
>AUTHOR</H2
@ -662,7 +703,7 @@ HREF="mailto:maf@splintered.net"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN213"
NAME="AEN231"
></A
><H2
>SEE ALSO</H2

View file

@ -1,6 +1,6 @@
<!DOCTYPE refentry PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
<!-- $Id: otp-control.sgml 80 2009-12-26 23:25:04Z maf $ -->
<!-- $Id: otp-control.sgml 169 2011-05-11 04:10:57Z maf $ -->
<refentry>
@ -25,18 +25,20 @@ Local user database configuration for One Time Password package.
<command>otp-control</command>
<arg>-?hnv</arg>
<arg>-c<replaceable> count</replaceable></arg>
<arg>-C<replaceable> count_ceil</replaceable></arg>
<arg>-C<replaceable> count_ceiling</replaceable></arg>
<arg>-f<replaceable> format</replaceable></arg>
<arg>-F<replaceable> flags</replaceable></arg>
<arg>-F<replaceable> flag</replaceable></arg>
<arg>-H<replaceable> sc_hostname</replaceable></arg>
<arg>-I<replaceable> sc_index</replaceable></arg>
<arg>-k<replaceable> key</replaceable></arg>
<arg>-l<replaceable> location</replaceable></arg>
<arg>-m<replaceable> command_mode</replaceable></arg>
<arg>-o<replaceable> otpdb_pathname</replaceable></arg>
<arg>-o<replaceable> otp_db</replaceable></arg>
<arg>-s<replaceable> status</replaceable></arg>
<arg>-S<replaceable> sc_flags</replaceable></arg>
<arg>-t<replaceable> type</replaceable></arg>
<arg>-u<replaceable> username</replaceable></arg>
<arg>-V<replaceable> service_name</replaceable></arg>
<arg>-w<replaceable> window</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
@ -56,7 +58,7 @@ and removed by <command>otp-control.</command>
<variablelist>
<varlistentry>
<term>-c<replaceable> count</replaceable></term>
<term>-c, --count= <replaceable> count</replaceable></term>
<listitem>
<para>
User count. The count increases with each OTP transaction.
@ -65,7 +67,7 @@ User count. The count increases with each OTP transaction.
</varlistentry>
<varlistentry>
<term>-C<replaceable> count_ceil</replaceable></term>
<term>-C, --count-ceil= <replaceable> count_ceiling</replaceable></term>
<listitem>
<para>
User count ceiling. Highest count allowed for this user. Configuring
@ -76,9 +78,9 @@ A count value must only be allowed for authentication once.
</para><para>
Example:
</para><para>
host=h1, user=bob, count_current=0, count_ceil=10000.
host=h1, user=bob, count_current=0, count_ceiling=10000.
</para><para>
host=h2, user=bob, count_current=10001, count_ceil=20000.
host=h2, user=bob, count_current=10001, count_ceiling=20000.
</para><para>
The number of keys a user must possess is decreased at the expense
of security dependencies among multiple systems. If system A is
@ -93,7 +95,7 @@ system database during authentication.
</varlistentry>
<varlistentry>
<term>-f</term>
<term>-f, --format=</term>
<listitem>
<para>
OTP format. One of hex40 dhex40 dec31.6 dec31.7 dec31.8 dec31.9 dec31.10.
@ -107,14 +109,15 @@ default in future releases.
</varlistentry>
<varlistentry>
<term>-F</term>
<term>-F, --flag=</term>
<listitem>
<para>
OTP flags. All flags are unset by default.
OTP flag. All flags are unset by default.
<screen>
Flag Description
-----------------------------------------------------------------
display-count : Display HOTP count when prompted for challenge.
send-token : Send token to user out of band.
</screen>
</para>
</listitem>
@ -122,7 +125,7 @@ OTP flags. All flags are unset by default.
<varlistentry>
<term>-h</term>
<term>-h, --help</term>
<listitem>
<para>
Help.
@ -132,25 +135,25 @@ Help.
<varlistentry>
<term>-H<replaceable> sc_hostname</replaceable></term>
<term>-H, --sc_hostname=<replaceable> sc_hostname</replaceable></term>
<listitem>
<para>
Set the SC hostname with the list-sc command mode.
Set the SC hostname for the list-sc command mode.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-I<replaceable> sc_index</replaceable></term>
<term>-I, --sc_index=<replaceable> sc_index</replaceable></term>
<listitem>
<para>
Set the SC index with the list-sc command mode.
Set the SC index for the list-sc command mode.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-k<replaceable> key</replaceable></term>
<term>-k, --key=<replaceable> key</replaceable></term>
<listitem>
<para>
160 bit shared secret key in ASCII HEX. The secret key is shared between
@ -163,7 +166,16 @@ C0C3D47F1CC68ECE0DF81D008F0C0D72D43EB745
</varlistentry>
<varlistentry>
<term>-m<replaceable> command_mode</replaceable></term>
<term>-l, --location=<replaceable> location</replaceable></term>
<listitem>
<para>
Location to send token to when SEND_TOKEN flag is set.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-m, --command_mode=<replaceable> command_mode</replaceable></term>
<listitem>
<para>
</para>
@ -178,6 +190,7 @@ C0C3D47F1CC68ECE0DF81D008F0C0D72D43EB745
list-sc - List user record (SC friendly)
load - ASCII load user record(s)
remove - Remove user
send-token - Send token to user
set-count - Set user count
set-count-ceil - Set user count ceiling
set-flags - Set user flags
@ -190,7 +203,7 @@ C0C3D47F1CC68ECE0DF81D008F0C0D72D43EB745
</varlistentry>
<varlistentry>
<term>-n</term>
<term>-n, --create_database</term>
<listitem>
<para>
Create new database if one does not exist.
@ -199,7 +212,7 @@ Create new database if one does not exist.
</varlistentry>
<varlistentry>
<term>-o<replaceable> otp_pathname</replaceable></term>
<term>-o, --otp-db=<replaceable> otp_db</replaceable></term>
<listitem>
<para>
Pathname of OTP database.
@ -208,7 +221,7 @@ Pathname of OTP database.
</varlistentry>
<varlistentry>
<term>-s<replaceable> otp_pathname</replaceable></term>
<term>-s, --status=<replaceable> status</replaceable></term>
<listitem>
<para>
OTP Status. The default status is active.
@ -219,7 +232,8 @@ OTP Status. The default status is active.
inactive : OTP may not be required for successful authentication.
The OTP authentication module may be configured to allow
inactive accounts to authenticate. This may be used to
temporarily remove the OTP authentication method for a user.
temporarily remove the OTP authentication method for a
user.
disabled : Account is disabled. OTP authentication will fail.
</screen>
</para>
@ -228,16 +242,16 @@ OTP Status. The default status is active.
<varlistentry>
<term>-S<replaceable> sc_flags</replaceable></term>
<term>-S, --sc-flags=<replaceable> sc_flags</replaceable></term>
<listitem>
<para>
Set the SC flags with the list-sc command mode. 0=CHALLENGE, 1=READERKEY.
Set the SC flags for the list-sc command mode. 0=CHALLENGE, 1=READERKEY.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-t<replaceable> type</replaceable></term>
<term>-t, --type=<replaceable> type</replaceable></term>
<listitem>
<para>
OTP Type. RFC 4226 HOTP is only supported type.
@ -246,7 +260,7 @@ OTP Type. RFC 4226 HOTP is only supported type.
</varlistentry>
<varlistentry>
<term>-u<replaceable> username</replaceable></term>
<term>-u, --username=<replaceable> username</replaceable></term>
<listitem>
<para>
Username to perform database operation on.
@ -255,7 +269,7 @@ Username to perform database operation on.
</varlistentry>
<varlistentry>
<term>-v</term>
<term>-v, --verbose</term>
<listitem>
<para>
Enable verbose output (debugging).
@ -264,7 +278,25 @@ Enable verbose output (debugging).
</varlistentry>
<varlistentry>
<term>-w<replaceable> window</replaceable></term>
<term>-V, --service-name=<replaceable> service_name</replaceable></term>
<listitem>
<para>
Set service name for send-token function.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>--version</term>
<listitem>
<para>
Display software version.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-w, --challenge-window=<replaceable> window</replaceable></term>
<listitem>
<para>
Set the maximum window (count above the system count) where an OTP
@ -305,7 +337,7 @@ user stored in a separate ASCII : delimited file in base_dir/d.
: dump user database in ASCII. User records are separated by a newline.
Fields are : separated. All fields except the username are HEX encoded.
</para><para>
#version:user:key:status:format:type:flags:count_cur:count_ceil:last
#version:user:key:status:format:type:flags:count_cur:count_ceiling:last
01:test:1111111111111111111111111111111111111111:01:01:01:00:00000000000003E8:00000000000007D0:0000000000000000
</para>
@ -446,7 +478,7 @@ Use the load command to import records in this format.
<command>otp-control -m dump</command>
</para>
<screen>
#version:user:key:status:format:type:flags:count_cur:count_ceil:last
#version:user:key:status:format:type:flags:count_cur:count_ceiling:last
01:bob:C381739834A63A67B0B9F7F7D36C8C567F6BFB3D:01:01:01:00:0000000000000001:FFFFFFFFFFFFFFFF:000000004AA02F9E
</screen>
</informalexample>

View file

@ -56,7 +56,7 @@
\fBotp-ov-plugin\fP \(em OpenVPN plug-in authentication module for OTP database\&.
.SH "SYNOPSIS"
.PP
\fBotp-ov-plugin\fP [-?hv] [-o\fI otpdb_fname\fP] [-w\fI otp_window\fP]
\fBotp-ov-plugin\fP [-?hv] [-o\fI otpdb_fname\fP] [-V\fI service_name\fP] [-w\fI otp_window\fP]
.SH "DESCRIPTION"
.PP
The \fBotp-ov-plugin\fP command is plug-in authentication
@ -68,14 +68,21 @@ A successful authentication will set a return code of
\fB1\fR, and program failure
\fB-1\fR\&.
.SH "OPTIONS"
.IP "-h" 10
.IP "-h, --help" 10
Help
.IP "-o\fI otpdb_pathname\fP" 10
.IP "-o, --otp-db=\fI otpdb_pathname\fP" 10
Pathname of OTP database\&.
.IP "-v" 10
.IP "-u, --otp-allow-unknown-user" 10
Allow users which do not exist in the OTP database to successfully
authenticate without using a One Time Password\&.
.IP "-V, --service-name=\fI service_name\fP" 10
Set service name for send-token function\&.
.IP "-v, --verbose" 10
Verbose
.IP "-w" 10
.IP "-w, --otp-challenge-window=" 10
Set the OTP challenge window\&.
.IP "--version" 10
Display software version\&.
.SH "EXAMPLES"
.PP
Test the module with user bob\&.
@ -103,4 +110,4 @@ Mark Fullmer maf@splintered\&.net
\fBbcload\fP(1)
\fBOpenVPN\fP(8)
spyrus-par2(7)
...\" created by instant / docbook-to-man, Sun 27 Dec 2009, 22:01
...\" created by instant / docbook-to-man, Sun 15 May 2011, 23:57

View file

@ -48,6 +48,11 @@ CLASS="REPLACEABLE"
><I
> otpdb_fname</I
></TT
>] [-V<TT
CLASS="REPLACEABLE"
><I
> service_name</I
></TT
>] [-w<TT
CLASS="REPLACEABLE"
><I
@ -58,7 +63,7 @@ CLASS="REPLACEABLE"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN18"
NAME="AEN20"
></A
><H2
>DESCRIPTION</H2
@ -99,7 +104,7 @@ CLASS="RETURNVALUE"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN27"
NAME="AEN29"
></A
><H2
>OPTIONS</H2
@ -109,13 +114,13 @@ NAME="AEN27"
CLASS="VARIABLELIST"
><DL
><DT
>-h</DT
>-h, --help</DT
><DD
><P
>Help</P
></DD
><DT
>-o<TT
>-o, --otp-db=<TT
CLASS="REPLACEABLE"
><I
> otpdb_pathname</I
@ -126,24 +131,48 @@ CLASS="REPLACEABLE"
>Pathname of OTP database.</P
></DD
><DT
>-v</DT
>-u, --otp-allow-unknown-user</DT
><DD
><P
>Allow users which do not exist in the OTP database to successfully
authenticate without using a One Time Password.</P
></DD
><DT
>-V, --service-name=<TT
CLASS="REPLACEABLE"
><I
> service_name</I
></TT
></DT
><DD
><P
>Set service name for send-token function.</P
></DD
><DT
>-v, --verbose</DT
><DD
><P
>Verbose</P
></DD
><DT
>-w</DT
>-w, --otp-challenge-window=</DT
><DD
><P
>Set the OTP challenge window.</P
></DD
><DT
>--version</DT
><DD
><P
>Display software version.</P
></DD
></DL
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AEN47"
NAME="AEN62"
></A
><H2
>EXAMPLES</H2
@ -152,7 +181,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN49"
NAME="AEN64"
></A
><P
>Test the module with user bob.</P
@ -181,7 +210,7 @@ CLASS="SCREEN"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN58"
NAME="AEN73"
></A
><H2
>AUTHOR</H2
@ -198,7 +227,7 @@ HREF="mailto:maf@splintered.net"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN65"
NAME="AEN80"
></A
><H2
>SEE ALSO</H2

View file

@ -1,6 +1,6 @@
<!DOCTYPE refentry PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
<!-- $Id: otp-ov-plugin.sgml 50 2009-12-15 01:37:19Z maf $ -->
<!-- $Id: otp-ov-plugin.sgml 177 2011-05-16 02:37:28Z maf $ -->
<refentry>
@ -25,6 +25,7 @@ OpenVPN plug-in authentication module for OTP database.
<command>otp-ov-plugin</command>
<arg>-?hv</arg>
<arg>-o<replaceable> otpdb_fname</replaceable></arg>
<arg>-V<replaceable> service_name</replaceable></arg>
<arg>-w<replaceable> otp_window</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
@ -49,7 +50,7 @@ A successful authentication will set a return code of
<variablelist>
<varlistentry>
<term>-h</term>
<term>-h, --help</term>
<listitem>
<para>
Help
@ -58,7 +59,7 @@ Help
</varlistentry>
<varlistentry>
<term>-o<replaceable> otpdb_pathname</replaceable></term>
<term>-o, --otp-db=<replaceable> otpdb_pathname</replaceable></term>
<listitem>
<para>
Pathname of OTP database.
@ -67,7 +68,26 @@ Pathname of OTP database.
</varlistentry>
<varlistentry>
<term>-v</term>
<term>-u, --otp-allow-unknown-user</term>
<listitem>
<para>
Allow users which do not exist in the OTP database to successfully
authenticate without using a One Time Password.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-V, --service-name=<replaceable> service_name</replaceable></term>
<listitem>
<para>
Set service name for send-token function.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-v, --verbose</term>
<listitem>
<para>
Verbose
@ -76,7 +96,7 @@ Verbose
</varlistentry>
<varlistentry>
<term>-w</term>
<term>-w, --otp-challenge-window=</term>
<listitem>
<para>
Set the OTP challenge window.
@ -84,6 +104,14 @@ Set the OTP challenge window.
</listitem>
</varlistentry>
<varlistentry>
<term>--version</term>
<listitem>
<para>
Display software version.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View file

@ -66,28 +66,30 @@ of {hostname,count,shared_key} are downloaded to the Smart Card using
Smart Card such as HOTP generation and PIN maintenance can be executed
with the appropriate administratative key\&.
.SH "OPTIONS"
.IP "-a\fI admin_keyfile\fP" 10
.IP "-a, --sc-admin-key=\fI admin_keyfile\fP" 10
Smart Card administratative key\&. The admin-enable command and
administratative key are used to toggle the Smart Card into admin mode\&.
Once in admin mode commands admin-disable, adminkey-set, balancecard-set,
host-get, host-set, pin-set, and sc-clear can be executed\&. The default admin
key, "3030303030303030303030303030303030303030" (HEX), should be changed to
restrict access to the above commands\&.
.IP "-c\fI count\fP" 10
.IP "-c, --sc-count=\fI count\fP" 10
Configure the count parameter optionally used by the hotp-gen command\&.
.IP "-d\fI debug_level\fP" 10
A count value of 0 indicates the HOTP value is to be calculated with the
current stored count\&.
.IP "-d, --debug=\fI debug_level\fP" 10
Set debug level\&.
.IP "-h" 10
.IP "-h, --help" 10
Help\&.
.IP "-i\fI index\fP" 10
.IP "-i, --sc-index=\fI index\fP" 10
Set the 8 bit index\&. The Smart Card contains numerically indexed records
for each host of the form {hostname,count,shared_key}\&. The firmware
will support indexes in the range 0\&.\&.254\&. 255 is reserved\&. Memory
capacity on the Smart Card may further restrict the index range\&. The
ZC3\&.9 BasicCard with firmware revision 3 supports up to 85 records\&.
.IP "-l" 10
.IP "-l, --list-readers" 10
List SC Readers
.IP "-m\fI command_mode\fP" 10
.IP "-m, --sc-command=\fI command_mode\fP" 10
.PP
.nf
Command Mode Description Notes Modifiers
@ -121,14 +123,16 @@ List SC Readers
d output in otpdb load friendly format\&.
r include reader key in request\&.
.fi
.IP "-M\fI modifiers\fP" 10
.IP "-M, --sc-command-modifier=\fI modifiers\fP" 10
Configure command_mode modifiers\&. Modifier d applied to the host-get
command will generate output in otpdb format\&. Count (c) and Host (h)
used with hotp-gen allow passing the Count and Host parameters
respectively\&. The Smart Card may not be configured to support
all variations of a command\&.
variations
.IP "-r\fI reader\fP" 10
.IP "-p, --no-pin" 10
Do not prompt for PIN\&. The Smart Card does not require a PIN when admin
mode is enabled\&.
.IP "-r, --reader=\fI reader\fP" 10
Set Smart Card reader\&. Use -l to list available readers\&. A reader
is defined as class:reader:[option]\&. PCSC and embedded
are the two available classes\&. The embedded class contains the acr30s driver
@ -137,7 +141,7 @@ If pcscd is running the first PC/SC reader will be the default followed by
the embedded acr30s driver\&. Use PCSC: for the first available PC/SC
reader\&. Use embedded:acr30s:/dev/cuaU0 for the embedded acr30s driver
with serial port /dev/cuaU0\&.
.IP "-R\fI reader_keyfile\fP" 10
.IP "-R, --sc-reader-key=\fI reader_keyfile\fP" 10
Smart Card Reader key\&. The reader-key-set command can be used
to set this key in the Smart Card\&. To emulate the behavior of
a reader using the key the r modifier may be used with this option
@ -148,20 +152,22 @@ key is "00000" or 3030303030\&.
.IP "" 10
This key must match the key set in the reader\&. With the Spyrus
PAR II reader this is set in the PAR II EEProm\&.
.IP "-u\fI username\fP" 10
.IP "-u, --sc-username=\fI username\fP" 10
Set username\&. The username is used with the host-get command and
d modifier\&.
.IP "-v\fI card_api_version\fP" 10
.IP "-v, --sc-version=\fI card_api_version\fP" 10
Set the Smart Card API version\&. The binary API between the terminal
and Smart Card changed between version 2 and 3\&. See command_mode notes
above\&. The default version is 3\&. Configuring version 2 will allow
maintenance of Smart Card with version 2 firmware\&.
.IP "--version" 10
Display software version\&.
.SH "SMART CARD COMMANDS"
.PP
\fBadmin-enable\fP : enable administrative mode\&. The commands admin-disable, admin-key-set,
balancecard-set, host-get, and sc-clear require admin mode to be enabled\&.
pin-set and commands requiring a PIN will not require a valid PIN while
the SC is in admin mode\&. A new key can be generated with
pin-set and commands accepting a PIN will not require the PIN to be valid
while the SC is in admin mode\&. A new key can be generated with
\fBopenssl rand 160 | openssl sha1\fP\&. The hotp-gen
command will automatically disable admin mode\&.
.PP
@ -229,7 +235,12 @@ F0: challenge (count) input is required by the user\&.
F1: enable reader authentication by the SC for the GetHOTP* commands\&.
F2\&.\&.F11: reserved
F2: enable base10 display
F3\&.\&.F7: reserved
F8-11: FMT3-FMT0\&. 0000=HEX40 0001=HEX40 0010=DEC31\&.6 0011=DEC31\&.7
0100=DEC31\&.8 0101=DEC31\&.9 0110=DEC31\&.10 0011=DHEX40
Example host record with index=0, count=7, hostname=dev1\&.eng,
key=E4AACE5EC7291C405ED28949BB6DACA05768319D
@ -417,4 +428,4 @@ Mark Fullmer maf@splintered\&.net
\fBbcload\fP(1)
\fBurd\fP(1)
spyrus-par2(7)
...\" created by instant / docbook-to-man, Sun 27 Dec 2009, 22:01
...\" created by instant / docbook-to-man, Sun 15 May 2011, 23:57

View file

@ -129,7 +129,7 @@ NAME="AEN39"
CLASS="VARIABLELIST"
><DL
><DT
>-a<TT
>-a, --sc-admin-key=<TT
CLASS="REPLACEABLE"
><I
> admin_keyfile</I
@ -145,7 +145,7 @@ key, "3030303030303030303030303030303030303030" (HEX), should be changed to
restrict access to the above commands.</P
></DD
><DT
>-c<TT
>-c, --sc-count=<TT
CLASS="REPLACEABLE"
><I
> count</I
@ -153,10 +153,12 @@ CLASS="REPLACEABLE"
></DT
><DD
><P
>Configure the count parameter optionally used by the hotp-gen command.</P
>Configure the count parameter optionally used by the hotp-gen command.
A count value of 0 indicates the HOTP value is to be calculated with the
current stored count.</P
></DD
><DT
>-d<TT
>-d, --debug=<TT
CLASS="REPLACEABLE"
><I
> debug_level</I
@ -167,13 +169,13 @@ CLASS="REPLACEABLE"
>Set debug level.</P
></DD
><DT
>-h</DT
>-h, --help</DT
><DD
><P
>Help.</P
></DD
><DT
>-i<TT
>-i, --sc-index=<TT
CLASS="REPLACEABLE"
><I
> index</I
@ -188,13 +190,13 @@ capacity on the Smart Card may further restrict the index range. The
ZC3.9 BasicCard with firmware revision 3 supports up to 85 records.</P
></DD
><DT
>-l</DT
>-l, --list-readers</DT
><DD
><P
>List SC Readers</P
></DD
><DT
>-m<TT
>-m, --sc-command=<TT
CLASS="REPLACEABLE"
><I
> command_mode</I
@ -237,7 +239,7 @@ CLASS="SCREEN"
r include reader key in request.&#13;</PRE
></DD
><DT
>-M<TT
>-M, --sc-command-modifier=<TT
CLASS="REPLACEABLE"
><I
> modifiers</I
@ -249,11 +251,17 @@ CLASS="REPLACEABLE"
command will generate output in otpdb format. Count (c) and Host (h)
used with hotp-gen allow passing the Count and Host parameters
respectively. The Smart Card may not be configured to support
all variations of a command.
variations </P
all variations of a command.</P
></DD
><DT
>-r<TT
>-p, --no-pin</DT
><DD
><P
>Do not prompt for PIN. The Smart Card does not require a PIN when admin
mode is enabled.</P
></DD
><DT
>-r, --reader=<TT
CLASS="REPLACEABLE"
><I
> reader</I
@ -277,7 +285,7 @@ reader. Use embedded:acr30s:/dev/cuaU0 for the embedded acr30s driver
with serial port /dev/cuaU0.</P
></DD
><DT
>-R<TT
>-R, --sc-reader-key=<TT
CLASS="REPLACEABLE"
><I
> reader_keyfile</I
@ -297,7 +305,7 @@ key is "00000" or 3030303030.</P
PAR II reader this is set in the PAR II EEProm.</P
></DD
><DT
>-u<TT
>-u, --sc-username=<TT
CLASS="REPLACEABLE"
><I
> username</I
@ -309,7 +317,7 @@ CLASS="REPLACEABLE"
d modifier.</P
></DD
><DT
>-v<TT
>-v, --sc-version=<TT
CLASS="REPLACEABLE"
><I
> card_api_version</I
@ -322,13 +330,19 @@ and Smart Card changed between version 2 and 3. See command_mode notes
above. The default version is 3. Configuring version 2 will allow
maintenance of Smart Card with version 2 firmware.</P
></DD
><DT
>--version</DT
><DD
><P
>Display software version.</P
></DD
></DL
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AEN105"
NAME="AEN113"
></A
><H2
>SMART CARD COMMANDS</H2
@ -339,8 +353,8 @@ CLASS="COMMAND"
>
: enable administrative mode. The commands admin-disable, admin-key-set,
balancecard-set, host-get, and sc-clear require admin mode to be enabled.
pin-set and commands requiring a PIN will not require a valid PIN while
the SC is in admin mode. A new key can be generated with
pin-set and commands accepting a PIN will not require the PIN to be valid
while the SC is in admin mode. A new key can be generated with
<B
CLASS="COMMAND"
>openssl rand 160 | openssl sha1</B
@ -434,7 +448,12 @@ CLASS="SCREEN"
F1: enable reader authentication by the SC for the GetHOTP* commands.
F2..F11: reserved
F2: enable base10 display
F3..F7: reserved
F8-11: FMT3-FMT0. 0000=HEX40 0001=HEX40 0010=DEC31.6 0011=DEC31.7
0100=DEC31.8 0101=DEC31.9 0110=DEC31.10 0011=DHEX40
Example host record with index=0, count=7, hostname=dev1.eng,
key=E4AACE5EC7291C405ED28949BB6DACA05768319D
@ -573,7 +592,7 @@ CLASS="COMMAND"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN147"
NAME="AEN155"
></A
><H2
>EXAMPLES</H2
@ -582,7 +601,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN149"
NAME="AEN157"
></A
><P
>Change the administratative key from the default. Disable admin mode
@ -636,7 +655,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN160"
NAME="AEN168"
></A
><P
>Use <B
@ -697,7 +716,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN172"
NAME="AEN180"
></A
><P
>Dump card contents to stdout. Note fields are encoded in HEX including
@ -725,7 +744,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN177"
NAME="AEN185"
></A
><P
>Reset user PIN for card with secret.key as the admin key.</P
@ -770,7 +789,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN186"
NAME="AEN194"
></A
><P
>Generate HOTP for dev1. Use hostname-get to find the index for dev1. Use
@ -811,7 +830,7 @@ HOTP: 52DCD05FE5 -- dev1</SAMP
><DIV
CLASS="REFSECT1"
><A
NAME="AEN193"
NAME="AEN201"
></A
><H2
>AUTHOR</H2
@ -828,7 +847,7 @@ HREF="mailto:maf@splintered.net"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN200"
NAME="AEN208"
></A
><H2
>SEE ALSO</H2

View file

@ -1,6 +1,6 @@
<!DOCTYPE refentry PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
<!-- $Id: otp-sca.sgml 62 2009-12-18 17:26:31Z maf $ -->
<!-- $Id: otp-sca.sgml 126 2010-06-15 14:23:02Z maf $ -->
<refentry>
@ -55,7 +55,7 @@ with the appropriate administratative key.
<variablelist>
<varlistentry>
<term>-a<replaceable> admin_keyfile</replaceable></term>
<term>-a, --sc-admin-key=<replaceable> admin_keyfile</replaceable></term>
<listitem>
<para>
Smart Card administratative key. The admin-enable command and
@ -69,16 +69,18 @@ restrict access to the above commands.
</varlistentry>
<varlistentry>
<term>-c<replaceable> count</replaceable></term>
<term>-c, --sc-count=<replaceable> count</replaceable></term>
<listitem>
<para>
Configure the count parameter optionally used by the hotp-gen command.
A count value of 0 indicates the HOTP value is to be calculated with the
current stored count.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-d<replaceable> debug_level</replaceable></term>
<term>-d, --debug=<replaceable> debug_level</replaceable></term>
<listitem>
<para>
Set debug level.
@ -87,7 +89,7 @@ Set debug level.
</varlistentry>
<varlistentry>
<term>-h</term>
<term>-h, --help</term>
<listitem>
<para>
Help.
@ -96,7 +98,7 @@ Help.
</varlistentry>
<varlistentry>
<term>-i<replaceable> index</replaceable></term>
<term>-i, --sc-index=<replaceable> index</replaceable></term>
<listitem>
<para>
Set the 8 bit index. The Smart Card contains numerically indexed records
@ -108,7 +110,7 @@ ZC3.9 BasicCard with firmware revision 3 supports up to 85 records.
</listitem>
<varlistentry>
<term>-l</term>
<term>-l, --list-readers</term>
<listitem>
<para>
List SC Readers
@ -117,7 +119,7 @@ List SC Readers
</varlistentry>
<varlistentry>
<term>-m<replaceable> command_mode</replaceable></term>
<term>-m, --sc-command=<replaceable> command_mode</replaceable></term>
<listitem>
<para>
</para>
@ -158,7 +160,7 @@ List SC Readers
</varlistentry>
<varlistentry>
<term>-M<replaceable> modifiers</replaceable></term>
<term>-M, --sc-command-modifier=<replaceable> modifiers</replaceable></term>
<listitem>
<para>
Configure command_mode modifiers. Modifier d applied to the host-get
@ -166,13 +168,22 @@ command will generate output in otpdb format. Count (c) and Host (h)
used with hotp-gen allow passing the Count and Host parameters
respectively. The Smart Card may not be configured to support
all variations of a command.
variations
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-r<replaceable> reader</replaceable></term>
<term>-p, --no-pin</term>
<listitem>
<para>
Do not prompt for PIN. The Smart Card does not require a PIN when admin
mode is enabled.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-r, --reader=<replaceable> reader</replaceable></term>
<listitem>
<para>
Set Smart Card reader. Use -l to list available readers. A reader
@ -188,7 +199,7 @@ with serial port /dev/cuaU0.
</varlistentry>
<varlistentry>
<term>-R<replaceable> reader_keyfile</replaceable></term>
<term>-R, --sc-reader-key=<replaceable> reader_keyfile</replaceable></term>
<listitem>
<para>
Smart Card Reader key. The reader-key-set command can be used
@ -208,7 +219,7 @@ PAR II reader this is set in the PAR II EEProm.
</varlistentry>
<varlistentry>
<term>-u<replaceable> username</replaceable></term>
<term>-u, --sc-username=<replaceable> username</replaceable></term>
<listitem>
<para>
Set username. The username is used with the host-get command and
@ -218,7 +229,7 @@ d modifier.
</varlistentry>
<varlistentry>
<term>-v<replaceable> card_api_version</replaceable></term>
<term>-v, --sc-version=<replaceable> card_api_version</replaceable></term>
<listitem>
<para>
Set the Smart Card API version. The binary API between the terminal
@ -229,6 +240,14 @@ maintenance of Smart Card with version 2 firmware.
</listitem>
</varlistentry>
<varlistentry>
<term>--version</term>
<listitem>
<para>
Display software version.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
@ -240,8 +259,8 @@ maintenance of Smart Card with version 2 firmware.
<command>admin-enable</command>
: enable administrative mode. The commands admin-disable, admin-key-set,
balancecard-set, host-get, and sc-clear require admin mode to be enabled.
pin-set and commands requiring a PIN will not require a valid PIN while
the SC is in admin mode. A new key can be generated with
pin-set and commands accepting a PIN will not require the PIN to be valid
while the SC is in admin mode. A new key can be generated with
<command>openssl rand 160 | openssl sha1</command>. The hotp-gen
command will automatically disable admin mode.
</para>
@ -318,7 +337,12 @@ F0: challenge (count) input is required by the user.
F1: enable reader authentication by the SC for the GetHOTP* commands.
F2..F11: reserved
F2: enable base10 display
F3..F7: reserved
F8-11: FMT3-FMT0. 0000=HEX40 0001=HEX40 0010=DEC31.6 0011=DEC31.7
0100=DEC31.8 0101=DEC31.9 0110=DEC31.10 0011=DHEX40
Example host record with index=0, count=7, hostname=dev1.eng,
key=E4AACE5EC7291C405ED28949BB6DACA05768319D

View file

@ -62,23 +62,25 @@
The \fBotp-sct\fP command is a user interface to generating
One Time Passwords with a Smart Card loaded with OTP software\&.
.SH "OPTIONS"
.IP "-c\fI count\fP" 10
.IP "-c, --sc-count=\fI count\fP" 10
Configure the optional count parameter to sync a Smart Card to a challenge\&.
.IP "-d\fI debug_level\fP" 10
A count value of 0 indicates the HOTP value is to be calculated with the
current stored count\&.
.IP "-d, --debug=\fI debug_level\fP" 10
Set debug level\&.
.IP "-h" 10
.IP "-h, --help" 10
Help\&.
.IP "-i\fI index\fP" 10
.IP "-i, --sc-index=\fI index\fP" 10
Set the 8 bit index\&. The Smart Card contains numerically indexed records
for each host system\&. Use the -l option to list hostnames associated with
the index\&. The default index is 0\&.
.IP "-l" 10
.IP "-l, --list-readers" 10
List SC Readers
.IP "-L" 10
.IP "-L, --sc-list-hostnames" 10
List host systems configured on the Smart Card\&. The index is used with the -i option\&.
.IP "-o" 10
.IP "-p, --sc-reset-pin" 10
Set new PIN\&.
.IP "-r\fI reader\fP" 10
.IP "-r, --reader=\fI reader\fP" 10
Set Smart Card reader\&. Use -l to list available readers\&. A reader
is defined as class:reader:[option]\&. PCSC and embedded
are the two available classes\&. The embedded class contains the acr30s driver
@ -87,17 +89,19 @@ If pcscd is running the first PC/SC reader will be the default followed by
the embedded acr30s driver\&. Use PCSC: for the first available PC/SC
reader\&. Use embedded:acr30s:/dev/cuaU0 for the embedded acr30s driver
with serial port /dev/cuaU0\&.
.IP "-v\fI card_api_version\fP" 10
.IP "-v, --sc-version=\fI card_api_version\fP" 10
Set the Smart Card API version\&. The binary API between the terminal
and Smart Card changed between version 2 and 3\&. See command mode notes
above\&. The default version is 3\&. Configuring version 2 will allow
maintenance of Smart Card with version 2 firmware\&.
.IP "-V" 10
.IP "-V, --sc-list-version" 10
List the Smart Card firmware version\&.
.IP "-1" 10
.IP "-1, --sc-get-hostp-v1" 10
Use the version 1 GetHOTP command instead of the default GetHOTPHostCount32\&.
The latter is not available on firmware revision 1\&. GetHOTP may be conditionally
compiled out of newer firmware\&.
.IP "--version" 10
Display software version\&.
.SH "EXAMPLES"
.PP
Generate a HOTP for the first system on the first PCSC reader found\&.
@ -138,4 +142,4 @@ Mark Fullmer maf@splintered\&.net
\fBbcload\fP(1)
\fBurd\fP(1)
spyrus-par2(7)
...\" created by instant / docbook-to-man, Sun 27 Dec 2009, 22:01
...\" created by instant / docbook-to-man, Sun 15 May 2011, 23:57

View file

@ -97,7 +97,7 @@ NAME="AEN28"
CLASS="VARIABLELIST"
><DL
><DT
>-c<TT
>-c, --sc-count=<TT
CLASS="REPLACEABLE"
><I
> count</I
@ -105,10 +105,12 @@ CLASS="REPLACEABLE"
></DT
><DD
><P
>Configure the optional count parameter to sync a Smart Card to a challenge.</P
>Configure the optional count parameter to sync a Smart Card to a challenge.
A count value of 0 indicates the HOTP value is to be calculated with the
current stored count.</P
></DD
><DT
>-d<TT
>-d, --debug=<TT
CLASS="REPLACEABLE"
><I
> debug_level</I
@ -119,13 +121,13 @@ CLASS="REPLACEABLE"
>Set debug level.</P
></DD
><DT
>-h</DT
>-h, --help</DT
><DD
><P
>Help.</P
></DD
><DT
>-i<TT
>-i, --sc-index=<TT
CLASS="REPLACEABLE"
><I
> index</I
@ -138,25 +140,25 @@ for each host system. Use the -l option to list hostnames associated with
the index. The default index is 0.</P
></DD
><DT
>-l</DT
>-l, --list-readers</DT
><DD
><P
>List SC Readers</P
></DD
><DT
>-L</DT
>-L, --sc-list-hostnames</DT
><DD
><P
>List host systems configured on the Smart Card. The index is used with the -i option.</P
></DD
><DT
>-o</DT
>-p, --sc-reset-pin</DT
><DD
><P
>Set new PIN.</P
></DD
><DT
>-r<TT
>-r, --reader=<TT
CLASS="REPLACEABLE"
><I
> reader</I
@ -180,7 +182,7 @@ reader. Use embedded:acr30s:/dev/cuaU0 for the embedded acr30s driver
with serial port /dev/cuaU0.</P
></DD
><DT
>-v<TT
>-v, --sc-version=<TT
CLASS="REPLACEABLE"
><I
> card_api_version</I
@ -194,26 +196,32 @@ above. The default version is 3. Configuring version 2 will allow
maintenance of Smart Card with version 2 firmware.</P
></DD
><DT
>-V</DT
>-V, --sc-list-version</DT
><DD
><P
>List the Smart Card firmware version.</P
></DD
><DT
>-1</DT
>-1, --sc-get-hostp-v1</DT
><DD
><P
>Use the version 1 GetHOTP command instead of the default GetHOTPHostCount32.
The latter is not available on firmware revision 1. GetHOTP may be conditionally
compiled out of newer firmware.</P
></DD
><DT
>--version</DT
><DD
><P
>Display software version.</P
></DD
></DL
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AEN82"
NAME="AEN86"
></A
><H2
>EXAMPLES</H2
@ -222,7 +230,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN84"
NAME="AEN88"
></A
><P
>Generate a HOTP for the first system on the first PCSC reader found.</P
@ -246,7 +254,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN89"
NAME="AEN93"
></A
><P
>List systems configured on Smart Card in default reader. Generate HOTP
@ -290,7 +298,7 @@ CLASS="COMMAND"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN98"
NAME="AEN102"
></A
><H2
>AUTHOR</H2
@ -307,7 +315,7 @@ HREF="mailto:maf@splintered.net"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN105"
NAME="AEN109"
></A
><H2
>SEE ALSO</H2

View file

@ -1,6 +1,6 @@
<!DOCTYPE refentry PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
<!-- $Id: otp-sct.sgml 62 2009-12-18 17:26:31Z maf $ -->
<!-- $Id: otp-sct.sgml 126 2010-06-15 14:23:02Z maf $ -->
<refentry>
@ -32,7 +32,6 @@ Smart Card Terminal for One Time Password package.
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
<title>DESCRIPTION</title>
<para>
@ -46,16 +45,18 @@ One Time Passwords with a Smart Card loaded with OTP software.
<variablelist>
<varlistentry>
<term>-c<replaceable> count</replaceable></term>
<term>-c, --sc-count=<replaceable> count</replaceable></term>
<listitem>
<para>
Configure the optional count parameter to sync a Smart Card to a challenge.
A count value of 0 indicates the HOTP value is to be calculated with the
current stored count.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-d<replaceable> debug_level</replaceable></term>
<term>-d, --debug=<replaceable> debug_level</replaceable></term>
<listitem>
<para>
Set debug level.
@ -64,7 +65,7 @@ Set debug level.
</varlistentry>
<varlistentry>
<term>-h</term>
<term>-h, --help</term>
<listitem>
<para>
Help.
@ -73,7 +74,7 @@ Help.
</varlistentry>
<varlistentry>
<term>-i<replaceable> index</replaceable></term>
<term>-i, --sc-index=<replaceable> index</replaceable></term>
<listitem>
<para>
Set the 8 bit index. The Smart Card contains numerically indexed records
@ -83,7 +84,7 @@ the index. The default index is 0.
</listitem>
<varlistentry>
<term>-l</term>
<term>-l, --list-readers</term>
<listitem>
<para>
List SC Readers
@ -92,7 +93,7 @@ List SC Readers
</varlistentry>
<varlistentry>
<term>-L</term>
<term>-L, --sc-list-hostnames</term>
<listitem>
<para>
List host systems configured on the Smart Card. The index is used with the -i option.
@ -101,7 +102,7 @@ List host systems configured on the Smart Card. The index is used with the -i o
</varlistentry>
<varlistentry>
<term>-o</term>
<term>-p, --sc-reset-pin</term>
<listitem>
<para>
Set new PIN.
@ -110,7 +111,7 @@ Set new PIN.
</varlistentry>
<varlistentry>
<term>-r<replaceable> reader</replaceable></term>
<term>-r, --reader=<replaceable> reader</replaceable></term>
<listitem>
<para>
Set Smart Card reader. Use -l to list available readers. A reader
@ -126,7 +127,7 @@ with serial port /dev/cuaU0.
</varlistentry>
<varlistentry>
<term>-v<replaceable> card_api_version</replaceable></term>
<term>-v, --sc-version=<replaceable> card_api_version</replaceable></term>
<listitem>
<para>
Set the Smart Card API version. The binary API between the terminal
@ -138,7 +139,7 @@ maintenance of Smart Card with version 2 firmware.
</varlistentry>
<varlistentry>
<term>-V</term>
<term>-V, --sc-list-version</term>
<listitem>
<para>
List the Smart Card firmware version.
@ -147,7 +148,7 @@ List the Smart Card firmware version.
</varlistentry>
<varlistentry>
<term>-1</term>
<term>-1, --sc-get-hostp-v1</term>
<listitem>
<para>
Use the version 1 GetHOTP command instead of the default GetHOTPHostCount32.
@ -157,6 +158,15 @@ compiled out of newer firmware.
</listitem>
</varlistentry>
<varlistentry>
<term>--version</term>
<listitem>
<para>
Display software version.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View file

@ -75,10 +75,18 @@ the display_count option is set\&. The default behavior will not display
the count unless the user record flags field has OTP_USER_FLAGS_DSPCNT set\&.
.IP "\fIrequire_db_entry\fP" 10
A user not in the OTP database will be denied access with the
require_db_entry option is set\&. By default users not in the OTP
database are permitted\&.
require_db_entry option is set\&. This option is set by default\&.
require_db_entry and allow_unknown user set the same flag and are
mutually exclusive\&.
.IP "\fIallow_unknown_user\fP" 10
A user not in the OTP database will be allowed access with the
allow_unknown_user option set\&. This option is disabled by default\&.
require_db_entry and allow_unknown user set the same flag and are
mutually exclusive\&.
.IP "\fIotpdb=\fP\fBalternate_otpdb\fP" 10
\fBalternate_otpdb\fP is used as the OTP database\&.
.IP "\fIservice=\fP\fBservice_name\fP" 10
Service name for use with send-token option\&.
.IP "\fIwindow=window\fP" 10
Set OTP challenge window\&.
.SH "AUTHOR"
@ -95,4 +103,4 @@ Mark Fullmer maf@splintered\&.net
\fBbcload\fP(1)
\fBpam\fP(8)
spyrus-par2(7)
...\" created by instant / docbook-to-man, Sun 27 Dec 2009, 22:01
...\" created by instant / docbook-to-man, Sun 15 May 2011, 23:57

View file

@ -128,8 +128,23 @@ CLASS="REPLACEABLE"
><DD
><P
>A user not in the OTP database will be denied access with the
require_db_entry option is set. By default users not in the OTP
database are permitted.</P
require_db_entry option is set. This option is set by default.
require_db_entry and allow_unknown user set the same flag and are
mutually exclusive.</P
></DD
><DT
><TT
CLASS="REPLACEABLE"
><I
>allow_unknown_user</I
></TT
></DT
><DD
><P
>A user not in the OTP database will be allowed access with the
allow_unknown_user option set. This option is disabled by default.
require_db_entry and allow_unknown user set the same flag and are
mutually exclusive.</P
></DD
><DT
><TT
@ -152,6 +167,20 @@ CLASS="FILENAME"
><TT
CLASS="REPLACEABLE"
><I
>service=</I
></TT
><TT
CLASS="FILENAME"
>service_name</TT
></DT
><DD
><P
>Service name for use with send-token option.</P
></DD
><DT
><TT
CLASS="REPLACEABLE"
><I
>window=window</I
></TT
></DT
@ -165,7 +194,7 @@ CLASS="REPLACEABLE"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN58"
NAME="AEN69"
></A
><H2
>AUTHOR</H2
@ -182,7 +211,7 @@ HREF="mailto:maf@splintered.net"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN65"
NAME="AEN76"
></A
><H2
>SEE ALSO</H2

View file

@ -1,6 +1,6 @@
<!DOCTYPE refentry PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
<!-- $Id: pam_otp.sgml 50 2009-12-15 01:37:19Z maf $ -->
<!-- $Id: pam_otp.sgml 169 2011-05-11 04:10:57Z maf $ -->
<refentry>
@ -80,8 +80,21 @@ the count unless the user record flags field has OTP_USER_FLAGS_DSPCNT set.
<listitem>
<para>
A user not in the OTP database will be denied access with the
require_db_entry option is set. By default users not in the OTP
database are permitted.
require_db_entry option is set. This option is set by default.
require_db_entry and allow_unknown user set the same flag and are
mutually exclusive.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable>allow_unknown_user</replaceable></term>
<listitem>
<para>
A user not in the OTP database will be allowed access with the
allow_unknown_user option set. This option is disabled by default.
require_db_entry and allow_unknown user set the same flag and are
mutually exclusive.
</para>
</listitem>
</varlistentry>
@ -95,6 +108,15 @@ database are permitted.
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable>service=</replaceable><filename>service_name</filename></term>
<listitem>
<para>
Service name for use with send-token option.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable>window=window</replaceable></term>
<listitem>

View file

@ -100,7 +100,8 @@ index 0\&.
.PP
\fB<#>\fP Toggle Challenge/Count input\&. The per-host count, incremented
by 1 and stored on the SC after each HOTP generation can be overridden
with this option\&.
with this option\&. A count value of 0 indicates the HOTP value is to be
calculated with the current stored count\&.
.PP
\fB<DOWN>\fP Enable host menu\&.
.SS "Host Selection With Menu:"
@ -201,4 +202,4 @@ may not\&.
\fBurd\fP(1)
\fBbcload\fP(1)
\fBOpenVPN\fP(8)
...\" created by instant / docbook-to-man, Sun 27 Dec 2009, 22:01
...\" created by instant / docbook-to-man, Sun 15 May 2011, 23:57

View file

@ -150,7 +150,8 @@ CLASS="KEYSYM"
>#</SPAN
> Toggle Challenge/Count input. The per-host count, incremented
by 1 and stored on the SC after each HOTP generation can be overridden
with this option.&#13;</P
with this option. A count value of 0 indicates the HOTP value is to be
calculated with the current stored count.&#13;</P
><P
><SPAN
CLASS="KEYSYM"

View file

@ -1,6 +1,6 @@
<!DOCTYPE refentry PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
<!-- $Id: spyrus-par2.sgml 78 2009-12-26 23:23:40Z maf $ -->
<!-- $Id: spyrus-par2.sgml 106 2009-12-30 10:24:34Z maf $ -->
<refentry>
@ -105,7 +105,8 @@ index 0.
<para>
<keysym>#</keysym> Toggle Challenge/Count input. The per-host count, incremented
by 1 and stored on the SC after each HOTP generation can be overridden
with this option.
with this option. A count value of 0 indicates the HOTP value is to be
calculated with the current stored count.
<para>
<keysym>DOWN</keysym> Enable host menu.

View file

@ -56,14 +56,14 @@
\fBurd\fP \(em Micro footprint RADIUS daemon with One Time Password support\&.
.SH "SYNOPSIS"
.PP
\fBurd\fP [-?AhdDOux] [-a\fI allowed_users_file\fP] [-b\fI local_ip\fP] [-B\fI local_port\fP] [-o\fI otp_db\fP] [-p\fI passwd_file\fP] [-P\fI pid_file\fP] [-s\fI secret_file\fP] [-w\fI otp_window\fP]
\fBurd\fP [-?AhcdDmMOux] [-a\fI authorized_users_file\fP] [-b\fI local_ip\fP] [-B\fI local_port\fP] [-o\fI otp_db\fP] [-p\fI passwd_file\fP] [-P\fI pid_file\fP] [-s\fI secret_file\fP] [-S\fI auth_service_name\fP] [-V\fI service_name\fP] [-w\fI otp_window\fP]
.SH "DESCRIPTION"
.PP
The \fBurd\fP daemon implements a minimal subset
of the RADIUS protocol for user authentication with optional
One Time Passwords\&. Accounting is not supported\&. Configuration
files include a \fBpasswd\fP file in Unix passwd(5)
format, an optional \fBallowed_users\fP file for
format, an optional \fBauthorized_users\fP file for
authenticating with a subset of the \fBpasswd\fP file, a
\fBsecret\fP file for the shared RADIUS secret, and
\fBotp_db\fP for One Time Password support\&.
@ -83,6 +83,12 @@ before any Read Modify Write operations are performed\&.
.PP
An alternate OTP database can be specified as \fBotb_db\fP\&.
.PP
PAM authentication is optionally supported for passwords\&. PAM can
be configured as the sole means of authentication, or the locally
configured password file may be used as a method of selecting valid
users to later be authenticated with PAM\&. PAM can be used for the
reusable password, the OTP API is always used for two factor authentication\&.
.PP
The \fBsecret\fP file contains the key shared
by the RADIUS NAS and RADIUS server\&. It must be less than 32 bytes\&.
.PP
@ -91,56 +97,71 @@ to authenticate successfully will toggle debugging and dump the internal
state and request cache respectively\&. If these users are not configured
with a password this feature will be disabled\&.
.SH "OPTIONS"
.IP "-a\fI allowed_users_file\fP" 10
Specify an alternate location for the \fBallowed_users_file\fP\&.
.IP "-a, --authorized-users-db=\fI authorized_users_file\fP" 10
Specify an alternate location for the \fBauthorized_users_file\fP\&.
.IP "" 10
The \fBallowed_users_file\fP contains one username per line\&.
The \fBauthorized_users_file\fP contains one username per line\&.
When configured this option requires a user to be listed
in \fBallowed_users_file\fP for authentication to proceed
in \fBauthorized_users_file\fP for authentication to proceed
with the password and One Time Password functions\&.
.IP "-A" 10
.IP "-A, --disable-authorized-users" 10
Disable \fBauthorized_users\fP feature\&. This option must
be set if the \fBauthorized_users_file\fP is not used\&.
.IP "-b\fI local_ip\fP" 10
.IP "-b, --bind-ip-address=\fI local_ip\fP" 10
Specify an IP address to bind(2) to\&. The default behavior will bind to
INADDR_ANY\&.
.IP "-B\fI local_port\fP" 10
.IP "-B, --bind-udp-port=\fI local_port\fP" 10
Specify the local UDP port to bind(2) to\&. The default behavior will bind
to UDP port 1812\&.
.IP "-d" 10
.IP "-c, --display-count" 10
Force count to be passed to RADIUS NAS\&. Not all devices will be able to
display this field\&.
.IP "-d, --debug=\fI debug_level\fP" 10
Enable verbose debugging\&.
.IP "-D" 10
.IP "-D, --disable-daemon-mode" 10
Disable daemon mode\&. When specified \fBurd\fP will not
run in the background and stdout is available for debugging information\&.
.IP "-o\fI otp_db\fP" 10
.IP "-m, --pam-authentication-enable" 10
Authenticate with PAM\&. The user must be present in the local password
and optionally authorized users files before PAM authentication\&.
.IP "-M, --pam-authentication-exclusive" 10
Authenticate with PAM\&. The local password file is not consulted\&.
.IP "-o, --otp-db=\fI otp_db\fP" 10
Specify an alternate location for the One Time Password database
\fBotp_db\fP\&.
.IP "-O" 10
.IP "-O, --otp-disable" 10
Disable the use of One Time Passwords\&.
.IP "-p\fI passwd_file\fP" 10
.IP "-p, --password-db=\fI passwd_file\fP" 10
Specify an alternate location for the \fBpasswd\fP file\&. The \fBpasswd\fP file is in Unix passwd(5) format\&.
Fields beyond the username and password hash are ignored\&. The users
password is hashed with crypt(3) and compared to the hash stored in this file
for authentication\&.
.IP "-P\fI pid_file\fP" 10
.IP "-P, --pidfile=\fI pid_file\fP" 10
Specify an alternate location for a file containing the process ID
of the RADIUS server\&. If a listen IP address or non standard UDP listen
port is configured the PID filename will contain the IP address and
port to differentiate it from other instances of \fBurd\fP running on the same server\&.
.IP "-s\fI secret_file\fP" 10
.IP "-s, --server-secret=\fI secret_file\fP" 10
Specify an alternate location for the \fBsecret_file\fP\&.
The \fBsecret_file\fP contains the shared secret between
the NAS and RADIUS server and must be less than 32 bytes\&.
.IP "-u" 10
.IP "-S, --pam-service-name=\fI auth_service_name\fP" 10
Specify an alternate name for the PAM authentication service\&. Defaults
to urd\&.
.IP "-u, --otp-allow-unknown-user" 10
Allow users which do not exist in the OTP database to successfully
authenticate without using a One Time Password, only a valid password
will be required\&.
.IP "-x" 10
.IP "-V, --service-name=\fI service_name\fP" 10
Set service name for send-token function\&.
.IP "--version" 10
Display software version\&.
.IP "-w, --otp-challenge-window=\fI window\fP" 10
Set the OTP challenge window\&.
.IP "-x, --debug-drop-udp-packets" 10
Drop every other RADIUS request from a NAS\&. This is a debugging feature
intended to stress test the reply cache code\&. The reply cache
implements state retention required for the use of One Time Passwords\&.
.IP "-w" 10
Set the OTP challenge window\&.
.SH "EXAMPLES"
.PP
The following command will start the urd server, bind it to IP address
@ -168,4 +189,4 @@ Mark Fullmer maf@splintered\&.net
\fBbcload\fP(1)
\fBotp-ov-plugin\fP(1)
spyrus-par2(7)
...\" created by instant / docbook-to-man, Sun 27 Dec 2009, 22:01
...\" created by instant / docbook-to-man, Sun 15 May 2011, 23:57

View file

@ -43,10 +43,10 @@ NAME="AEN10"
><B
CLASS="COMMAND"
>urd</B
> [-?AhdDOux] [-a<TT
> [-?AhcdDmMOux] [-a<TT
CLASS="REPLACEABLE"
><I
> allowed_users_file</I
> authorized_users_file</I
></TT
>] [-b<TT
CLASS="REPLACEABLE"
@ -78,6 +78,16 @@ CLASS="REPLACEABLE"
><I
> secret_file</I
></TT
>] [-S<TT
CLASS="REPLACEABLE"
><I
> auth_service_name</I
></TT
>] [-V<TT
CLASS="REPLACEABLE"
><I
> service_name</I
></TT
>] [-w<TT
CLASS="REPLACEABLE"
><I
@ -88,7 +98,7 @@ CLASS="REPLACEABLE"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN30"
NAME="AEN34"
></A
><H2
>DESCRIPTION</H2
@ -105,7 +115,7 @@ CLASS="FILENAME"
> file in Unix passwd(5)
format, an optional <TT
CLASS="FILENAME"
>allowed_users</TT
>authorized_users</TT
> file for
authenticating with a subset of the <TT
CLASS="FILENAME"
@ -168,6 +178,12 @@ CLASS="FILENAME"
>otb_db</TT
>.</P
><P
>PAM authentication is optionally supported for passwords. PAM can
be configured as the sole means of authentication, or the locally
configured password file may be used as a method of selecting valid
users to later be authenticated with PAM. PAM can be used for the
reusable password, the OTP API is always used for two factor authentication.</P
><P
>The <TT
CLASS="FILENAME"
>secret</TT
@ -182,7 +198,7 @@ with a password this feature will be disabled.</P
><DIV
CLASS="REFSECT1"
><A
NAME="AEN55"
NAME="AEN60"
></A
><H2
>OPTIONS</H2
@ -192,32 +208,32 @@ NAME="AEN55"
CLASS="VARIABLELIST"
><DL
><DT
>-a<TT
>-a, --authorized-users-db=<TT
CLASS="REPLACEABLE"
><I
> allowed_users_file</I
> authorized_users_file</I
></TT
></DT
><DD
><P
>Specify an alternate location for the <TT
CLASS="FILENAME"
>allowed_users_file</TT
>authorized_users_file</TT
>.</P
><P
>The <TT
CLASS="FILENAME"
>allowed_users_file</TT
>authorized_users_file</TT
> contains one username per line.
When configured this option requires a user to be listed
in <TT
CLASS="FILENAME"
>allowed_users_file</TT
>authorized_users_file</TT
> for authentication to proceed
with the password and One Time Password functions.</P
></DD
><DT
>-A</DT
>-A, --disable-authorized-users</DT
><DD
><P
>Disable <TT
@ -230,7 +246,7 @@ CLASS="FILENAME"
> is not used.</P
></DD
><DT
>-b<TT
>-b, --bind-ip-address=<TT
CLASS="REPLACEABLE"
><I
> local_ip</I
@ -242,7 +258,7 @@ CLASS="REPLACEABLE"
INADDR_ANY.</P
></DD
><DT
>-B<TT
>-B, --bind-udp-port=<TT
CLASS="REPLACEABLE"
><I
> local_port</I
@ -254,13 +270,25 @@ CLASS="REPLACEABLE"
to UDP port 1812.</P
></DD
><DT
>-d</DT
>-c, --display-count</DT
><DD
><P
>Force count to be passed to RADIUS NAS. Not all devices will be able to
display this field.</P
></DD
><DT
>-d, --debug=<TT
CLASS="REPLACEABLE"
><I
> debug_level</I
></TT
></DT
><DD
><P
>Enable verbose debugging.</P
></DD
><DT
>-D</DT
>-D, --disable-daemon-mode</DT
><DD
><P
>Disable daemon mode. When specified <B
@ -270,7 +298,20 @@ CLASS="COMMAND"
run in the background and stdout is available for debugging information.</P
></DD
><DT
>-o<TT
>-m, --pam-authentication-enable</DT
><DD
><P
>Authenticate with PAM. The user must be present in the local password
and optionally authorized users files before PAM authentication.</P
></DD
><DT
>-M, --pam-authentication-exclusive</DT
><DD
><P
>Authenticate with PAM. The local password file is not consulted.</P
></DD
><DT
>-o, --otp-db=<TT
CLASS="REPLACEABLE"
><I
> otp_db</I
@ -285,13 +326,13 @@ CLASS="FILENAME"
>.</P
></DD
><DT
>-O</DT
>-O, --otp-disable</DT
><DD
><P
>Disable the use of One Time Passwords.</P
></DD
><DT
>-p<TT
>-p, --password-db=<TT
CLASS="REPLACEABLE"
><I
> passwd_file</I
@ -312,7 +353,7 @@ password is hashed with crypt(3) and compared to the hash stored in this file
for authentication.</P
></DD
><DT
>-P<TT
>-P, --pidfile=<TT
CLASS="REPLACEABLE"
><I
> pid_file</I
@ -330,7 +371,7 @@ CLASS="COMMAND"
running on the same server.</P
></DD
><DT
>-s<TT
>-s, --server-secret=<TT
CLASS="REPLACEABLE"
><I
> secret_file</I
@ -349,7 +390,19 @@ CLASS="FILENAME"
the NAS and RADIUS server and must be less than 32 bytes.</P
></DD
><DT
>-u</DT
>-S, --pam-service-name=<TT
CLASS="REPLACEABLE"
><I
> auth_service_name</I
></TT
></DT
><DD
><P
>Specify an alternate name for the PAM authentication service. Defaults
to urd.</P
></DD
><DT
>-u, --otp-allow-unknown-user</DT
><DD
><P
>Allow users which do not exist in the OTP database to successfully
@ -357,26 +410,48 @@ authenticate without using a One Time Password, only a valid password
will be required.</P
></DD
><DT
>-x</DT
>-V, --service-name=<TT
CLASS="REPLACEABLE"
><I
> service_name</I
></TT
></DT
><DD
><P
>Set service name for send-token function.</P
></DD
><DT
>--version</DT
><DD
><P
>Display software version.</P
></DD
><DT
>-w, --otp-challenge-window=<TT
CLASS="REPLACEABLE"
><I
> window</I
></TT
></DT
><DD
><P
>Set the OTP challenge window.</P
></DD
><DT
>-x, --debug-drop-udp-packets</DT
><DD
><P
>Drop every other RADIUS request from a NAS. This is a debugging feature
intended to stress test the reply cache code. The reply cache
implements state retention required for the use of One Time Passwords.</P
></DD
><DT
>-w</DT
><DD
><P
>Set the OTP challenge window.</P
></DD
></DL
></DIV
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="AEN134"
NAME="AEN167"
></A
><H2
>EXAMPLES</H2
@ -385,7 +460,7 @@ CLASS="INFORMALEXAMPLE"
><P
></P
><A
NAME="AEN136"
NAME="AEN169"
></A
><P
>The following command will start the urd server, bind it to IP address
@ -419,7 +494,7 @@ CLASS="SCREEN"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN144"
NAME="AEN177"
></A
><H2
>AUTHOR</H2
@ -436,7 +511,7 @@ HREF="mailto:maf@splintered.net"
><DIV
CLASS="REFSECT1"
><A
NAME="AEN151"
NAME="AEN184"
></A
><H2
>SEE ALSO</H2

View file

@ -1,6 +1,6 @@
<!DOCTYPE refentry PUBLIC "-//Davenport//DTD DocBook V3.0//EN">
<!-- $Id: urd.sgml 50 2009-12-15 01:37:19Z maf $ -->
<!-- $Id: urd.sgml 178 2011-05-16 02:39:04Z maf $ -->
<refentry>
@ -23,14 +23,16 @@ Micro footprint RADIUS daemon with One Time Password support.
<refsynopsisdiv>
<cmdsynopsis>
<command>urd</command>
<arg>-?AhdDOux</arg>
<arg>-a<replaceable> allowed_users_file</replaceable></arg>
<arg>-?AhcdDmMOux</arg>
<arg>-a<replaceable> authorized_users_file</replaceable></arg>
<arg>-b<replaceable> local_ip</replaceable></arg>
<arg>-B<replaceable> local_port</replaceable></arg>
<arg>-o<replaceable> otp_db</replaceable></arg>
<arg>-p<replaceable> passwd_file</replaceable></arg>
<arg>-P<replaceable> pid_file</replaceable></arg>
<arg>-s<replaceable> secret_file</replaceable></arg>
<arg>-S<replaceable> auth_service_name</replaceable></arg>
<arg>-V<replaceable> service_name</replaceable></arg>
<arg>-w<replaceable> otp_window</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
@ -43,7 +45,7 @@ The <command>urd</command> daemon implements a minimal subset
of the RADIUS protocol for user authentication with optional
One Time Passwords. Accounting is not supported. Configuration
files include a <filename>passwd</filename> file in Unix passwd(5)
format, an optional <filename>allowed_users</filename> file for
format, an optional <filename>authorized_users</filename> file for
authenticating with a subset of the <filename>passwd</filename> file, a
<filename>secret</filename> file for the shared RADIUS secret, and
<filename>otp_db</filename> for One Time Password support.
@ -70,6 +72,13 @@ before any Read Modify Write operations are performed.
An alternate OTP database can be specified as <filename>otb_db</filename>.
</para>
<para>
PAM authentication is optionally supported for passwords. PAM can
be configured as the sole means of authentication, or the locally
configured password file may be used as a method of selecting valid
users to later be authenticated with PAM. PAM can be used for the
reusable password, the OTP API is always used for two factor authentication.
</para>
<para>
The <filename>secret</filename> file contains the key shared
by the RADIUS NAS and RADIUS server. It must be less than 32 bytes.
</para>
@ -86,22 +95,22 @@ with a password this feature will be disabled.
<variablelist>
<varlistentry>
<term>-a<replaceable> allowed_users_file</replaceable></term>
<term>-a, --authorized-users-db=<replaceable> authorized_users_file</replaceable></term>
<listitem>
<para>
Specify an alternate location for the <filename>allowed_users_file</filename>.
Specify an alternate location for the <filename>authorized_users_file</filename>.
</para>
<para>
The <filename>allowed_users_file</filename> contains one username per line.
The <filename>authorized_users_file</filename> contains one username per line.
When configured this option requires a user to be listed
in <filename>allowed_users_file</filename> for authentication to proceed
in <filename>authorized_users_file</filename> for authentication to proceed
with the password and One Time Password functions.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-A</term>
<term>-A, --disable-authorized-users</term>
<listitem>
<para>
Disable <filename>authorized_users</filename> feature. This option must
@ -111,7 +120,7 @@ be set if the <filename>authorized_users_file</filename> is not used.
</varlistentry>
<varlistentry>
<term>-b<replaceable> local_ip</replaceable></term>
<term>-b, --bind-ip-address=<replaceable> local_ip</replaceable></term>
<listitem>
<para>
Specify an IP address to bind(2) to. The default behavior will bind to
@ -121,7 +130,7 @@ INADDR_ANY.
</varlistentry>
<varlistentry>
<term>-B<replaceable> local_port</replaceable></term>
<term>-B, --bind-udp-port=<replaceable> local_port</replaceable></term>
<listitem>
<para>
Specify the local UDP port to bind(2) to. The default behavior will bind
@ -131,7 +140,17 @@ to UDP port 1812.
</varlistentry>
<varlistentry>
<term>-d</term>
<term>-c, --display-count</term>
<listitem>
<para>
Force count to be passed to RADIUS NAS. Not all devices will be able to
display this field.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-d, --debug=<replaceable> debug_level</replaceable></term>
<listitem>
<para>
Enable verbose debugging.
@ -140,7 +159,7 @@ Enable verbose debugging.
</varlistentry>
<varlistentry>
<term>-D</term>
<term>-D, --disable-daemon-mode</term>
<listitem>
<para>
Disable daemon mode. When specified <command>urd</command> will not
@ -150,7 +169,26 @@ run in the background and stdout is available for debugging information.
</varlistentry>
<varlistentry>
<term>-o<replaceable> otp_db</replaceable></term>
<term>-m, --pam-authentication-enable</term>
<listitem>
<para>
Authenticate with PAM. The user must be present in the local password
and optionally authorized users files before PAM authentication.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-M, --pam-authentication-exclusive</term>
<listitem>
<para>
Authenticate with PAM. The local password file is not consulted.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-o, --otp-db=<replaceable> otp_db</replaceable></term>
<listitem>
<para>
Specify an alternate location for the One Time Password database
@ -160,7 +198,7 @@ Specify an alternate location for the One Time Password database
</varlistentry>
<varlistentry>
<term>-O</term>
<term>-O, --otp-disable</term>
<listitem>
<para>
Disable the use of One Time Passwords.
@ -169,7 +207,7 @@ Disable the use of One Time Passwords.
</varlistentry>
<varlistentry>
<term>-p<replaceable> passwd_file</replaceable></term>
<term>-p, --password-db=<replaceable> passwd_file</replaceable></term>
<listitem>
<para>
Specify an alternate location for the <filename>passwd</filename>
@ -182,7 +220,7 @@ for authentication.
</varlistentry>
<varlistentry>
<term>-P<replaceable> pid_file</replaceable></term>
<term>-P, --pidfile=<replaceable> pid_file</replaceable></term>
<listitem>
<para>
Specify an alternate location for a file containing the process ID
@ -195,7 +233,7 @@ running on the same server.
</varlistentry>
<varlistentry>
<term>-s<replaceable> secret_file</replaceable></term>
<term>-s, --server-secret=<replaceable> secret_file</replaceable></term>
<listitem>
<para>
Specify an alternate location for the <filename>secret_file</filename>.
@ -206,7 +244,17 @@ the NAS and RADIUS server and must be less than 32 bytes.
</varlistentry>
<varlistentry>
<term>-u</term>
<term>-S, --pam-service-name=<replaceable> auth_service_name</replaceable></term>
<listitem>
<para>
Specify an alternate name for the PAM authentication service. Defaults
to urd.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-u, --otp-allow-unknown-user</term>
<listitem>
<para>
Allow users which do not exist in the OTP database to successfully
@ -217,18 +265,25 @@ will be required.
</varlistentry>
<varlistentry>
<term>-x</term>
<term>-V, --service-name=<replaceable> service_name</replaceable></term>
<listitem>
<para>
Drop every other RADIUS request from a NAS. This is a debugging feature
intended to stress test the reply cache code. The reply cache
implements state retention required for the use of One Time Passwords.
Set service name for send-token function.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-w</term>
<term>--version</term>
<listitem>
<para>
Display software version.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-w, --otp-challenge-window=<replaceable> window</replaceable></term>
<listitem>
<para>
Set the OTP challenge window.
@ -236,6 +291,17 @@ Set the OTP challenge window.
</listitem>
</varlistentry>
<varlistentry>
<term>-x, --debug-drop-udp-packets</term>
<listitem>
<para>
Drop every other RADIUS request from a NAS. This is a debugging feature
intended to stress test the reply cache code. The reply cache
implements state retention required for the use of One Time Passwords.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View file

@ -1,4 +1,4 @@
# $Id: Makefile 13 2009-11-26 16:37:03Z maf $
# $Id: Makefile 128 2010-06-15 14:25:09Z maf $
what:
@echo
@ -22,13 +22,18 @@ INSTALL=install -c -m0755
.c.o:; $(CC) $(CFLAGS) -c $*.c -o $*.o
OBJS = ../common/xerr.o
BINS = htsoft-downloader
BIN = htsoft-downloader
COBJS = ../common/xerr.o
OBJS = version.o ${BIN}.o
BINDIR=/usr/local/ootp/bin
all: htsoft-downloader.c ${OBJS} ${BINS}
all: version ${COBJS} ${OBJS} ${BIN}
version:
rm -f version.c; ../build/version ../VERSION ${BIN} > version.c
version.c:
install:
mkdir -p ${BINDIR}
@ -36,8 +41,8 @@ install:
@echo files installed in ${BINDIR}
clean:
/bin/rm -f ${BINS} htsoft-downloader.o
/bin/rm -f ${BINS} ${OBJS} version.c
htsoft-downloader: ${OBJS} htsoft-downloader.o
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o htsoft-downloader ${OBJS} htsoft-downloader.o $(LIBS)
${BIN}: ${COBJS} ${OBJS}
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o ${BIN} ${COBJS} ${OBJS} $(LIBS)

View file

@ -24,12 +24,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: htsoft-downloader.c 75 2009-12-26 20:59:23Z maf $
* $Id: htsoft-downloader.c 128 2010-06-15 14:25:09Z maf $
*/
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@ -89,6 +90,7 @@ int n2b(char *h, u_char *b);
int main(int argc, char **argv)
{
extern char *ootp_version;
struct termios pic_term;
char lbuf[1024];
char *c;
@ -97,9 +99,21 @@ int main(int argc, char **argv)
uint8_t ld_buf[256], ld_buf_len;
uint16_t h_load_offset, tmp_load_offset, buf_load_offset;
int i, r, pic_fd, lineno, lbuf_len, got_eof, pic_tmout, verbose;
int max_retries, ignore_last_wok_timeout;
int max_retries, ignore_last_wok_timeout, opt_version;
char *pic_dev;
struct option longopts[] = {
{ "serial-device", 1, (void*)0L, 'f'},
{ "help", 0, (void*)0L, 'h'},
{ "help", 0, (void*)0L, '?'},
{ "ignore-last-wok-timeout", 0, (void*)0L, 'i'},
{ "retries", 1, (void*)0L, 'r'},
{ "pic-timeout", 1, (void*)0L, 't'},
{ "verbose", 0, (void*)0L, 'v'},
{ "version", 0, &opt_version, 1},
{ 0, 0, 0, 0},
};
xerr_setid(argv[0]);
lineno = 0;
ld_buf_len = 0;
@ -111,8 +125,10 @@ int main(int argc, char **argv)
h_load_offset = 0;
buf_load_offset = 0;
ignore_last_wok_timeout = 0;
opt_version = 0;
while ((i = getopt(argc, argv, "f:h?ir:t:v:")) != -1) {
while ((i = getopt_long(argc, argv, "f:h?ir:t:v:", longopts,
(int*)0L)) != -1) {
switch (i) {
@ -142,14 +158,19 @@ int main(int argc, char **argv)
verbose = atoi(optarg);
break;
case 0:
if (opt_version) {
printf("%s\n", ootp_version);
exit(0);
}
default:
help();
exit(1);
break; /* notreached */
xerr_errx(1, "getopt_long(): fatal.");
break; /* not reached */
} /* switch */
} /* getopt */
} /* while getopt_long() */
/* open and setup serial communications port */
if ((pic_fd = open(pic_dev, O_RDWR)) < 0)

View file

@ -1,4 +1,4 @@
# $Id: Makefile 13 2009-11-26 16:37:03Z maf $
# $Id: Makefile 129 2010-06-15 14:25:43Z maf $
what:
@echo
@ -22,22 +22,27 @@ INSTALL=install -c -m0755
.c.o:; $(CC) $(CFLAGS) -c $*.c -o $*.o
OBJS = ../common/xerr.o ../common/str.o ../common/otplib.o ../common/ffdb.o
BINS = otp-control
BIN = otp-control
COBJS = ../common/xerr.o ../common/str.o ../common/otplib.o ../common/ffdb.o
OBJS = version.o ${BIN}.o
BINDIR=/usr/local/ootp/bin
all: otp-control.c ${OBJS} ${BINS}
all: version ${COBJS} ${OBJS} ${BIN}
version:
rm -f version.c; ../build/version ../VERSION ${BIN} > version.c
version.c:
install:
mkdir -p ${BINDIR}
${INSTALL} ${BINS} ${BINDIR}
${INSTALL} ${BIN} ${BINDIR}
@echo files installed in ${BINDIR}
clean:
/bin/rm -f ${BINS} otp-control.o
/bin/rm -f ${BIN} ${OBJS} version.c
otp-control: ${OBJS} otp-control.o
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o otp-control ${OBJS} otp-control.o $(LIBS)
${BIN}: ${COBJS} ${OBJS}
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o ${BIN} ${COBJS} ${OBJS} $(LIBS)

View file

@ -24,14 +24,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: otp-control.c 55 2009-12-17 01:59:35Z maf $
* $Id: otp-control.c 179 2011-05-16 02:48:42Z maf $
*/
#include <sys/types.h>
#include <sys/errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <inttypes.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include "otplib.h"
#include "otpsc.h"
@ -49,11 +50,13 @@
#define MODE_SET_COUNT_CEIL 11
#define MODE_TEST 12
#define MODE_CREATE 13
#define MODE_SEND_TOKEN 14
#define MODE_LIST_SC 18
#define MODE_SET_STATUS 19
#define MODE_SET_TYPE 20
#define MODE_SET_FORMAT 21
#define MODE_SET_FLAGS 22
#define MODE_SET_LOCATION 23
#define KEY_HEX160_LEN 40
@ -65,9 +68,11 @@ void help(void);
int main (int argc, char **argv)
{
extern char *ootp_version;
struct otp_ctx *otpctx;
struct otp_user ou;
int i, j, r, mode, window, db_flags, open_mode, open_op, verbose;
int opt_version, u_count_set;
char *otpdb_fname;
uint64_t u_count, u_count_ceil, count_offset, tmp64u;
uint8_t u_version, u_status, u_format, u_type, u_flags, sc_index;
@ -75,17 +80,42 @@ int main (int argc, char **argv)
unsigned char u_key160[20];
char key_hex160[KEY_HEX160_LEN+1];
char crsp_tmp[11];
char *u_username, *u_key_ascii, *sc_hostname;
char *endptr, *i_status, *i_format, *i_type, *i_flags;
char *u_username, *u_loc, *u_key_ascii, *sc_hostname;
char *endptr, *i_status, *i_format, *i_type, *i_flags, *service;
struct option longopts[] = {
{ "count", 1, (void*)0L, 'c'},
{ "count-ceil", 1, (void*)0L, 'C'},
{ "format", 1, (void*)0L, 'f'},
{ "flags", 1, (void*)0L, 'F'},
{ "sc-hostname", 1, (void*)0L, 'H'},
{ "sc-index", 1, (void*)0L, 'I'},
{ "key", 1, (void*)0L, 'k'},
{ "location", 1, (void*)0L, 'l'},
{ "command-mode", 1, (void*)0L, 'm'},
{ "otp-db", 1, (void*)0L, 'o'},
{ "status", 1, (void*)0L, 's'},
{ "sc-flags", 1, (void*)0L, 'S'},
{ "type", 1, (void*)0L, 't'},
{ "username", 1, (void*)0L, 'u'},
{ "challenge-window", 1, (void*)0L, 'w'},
{ "help", 0, (void*)0L, 'h'},
{ "create-database", 0, (void*)0L, 'n'},
{ "verbose", 0, (void*)0L, 'v'},
{ "service-name", 0, (void*)0L, 'V'},
{ "version", 0, &opt_version, 1},
{ 0, 0, 0, 0},
};
otpdb_fname = OTP_DB_FNAME;
sc_index = 0;
mode = 0;
window = 1;
verbose = 0;
u_count_set = 0;
db_flags = 0;
/* user defaults */
u_count = 0;
u_count = 1;
u_count_ceil = 0xFFFFFFFFFFFFFFFFLL;
u_version = OTP_VERSION;
u_format = OTP_FORMAT_HEX40;
@ -94,15 +124,19 @@ int main (int argc, char **argv)
u_flags = 0;
u_username = (char*)0L;
u_key_ascii = (char*)0L;
u_loc = (char*)0L;
endptr = (char*)0L;
sc_hostname = (char*)0L;
service = "otp-control";
bzero(sc_flags, SC_HOSTNAME_LEN);
i_status = i_type = i_format = i_flags = (char*)0L;
opt_version = 0;
/* init xerr */
xerr_setid(argv[0]);
while ((i = getopt(argc, argv, "c:C:hf:F:H:I:?k:m:no:s:S:t:u:w:v")) != -1) {
while ((i = getopt_long(argc, argv, "c:C:hf:F:H:I:?k:l:m:no:s:S:t:u:w:vV:",
longopts, (int*)0L)) != -1) {
switch (i) {
@ -110,6 +144,7 @@ int main (int argc, char **argv)
u_count = strtoull(optarg, &endptr, 0);
if (*endptr)
xerr_errx(1, "strtoull(%s): failed at %c.", optarg, *endptr);
u_count_set = 1;
break;
case 'C':
@ -146,6 +181,12 @@ int main (int argc, char **argv)
u_key_ascii = optarg;
break;
case 'l':
u_loc = optarg;
if (strlen(u_loc) > OTP_USER_LOC_LEN)
xerr_errx(1, "u_loc > OTP_USER_LOC_LEN");
break;
case 'm':
if (mode)
xerr_errx(1, "mode previously set.");
@ -166,6 +207,8 @@ int main (int argc, char **argv)
mode = MODE_LOAD;
} else if (!strcasecmp(optarg, "remove")) {
mode = MODE_REMOVE;
} else if (!strcasecmp(optarg, "send-token")) {
mode = MODE_SEND_TOKEN;
} else if (!strcasecmp(optarg, "set-count")) {
mode = MODE_SET_COUNT;
} else if (!strcasecmp(optarg, "set-count-ceil")) {
@ -174,6 +217,8 @@ int main (int argc, char **argv)
mode = MODE_SET_FLAGS;
} else if (!strcasecmp(optarg, "set-format")) {
mode = MODE_SET_FORMAT;
} else if (!strcasecmp(optarg, "set-location")) {
mode = MODE_SET_LOCATION;
} else if (!strcasecmp(optarg, "set-status")) {
mode = MODE_SET_STATUS;
} else if (!strcasecmp(optarg, "set-type")) {
@ -221,6 +266,10 @@ int main (int argc, char **argv)
verbose = 1;
break;
case 'V':
service = optarg;
break;
case 'h':
case '?':
help();
@ -230,6 +279,17 @@ int main (int argc, char **argv)
window = atoi(optarg);
break;
case 0:
if (opt_version) {
printf("%s\n", ootp_version);
exit(0);
}
break;
default:
xerr_errx(1, "getopt_long(): fatal.");
break; /* not reached */
} /* switch */
} /* while */
@ -272,6 +332,9 @@ int main (int argc, char **argv)
if ((mode == MODE_SET_STATUS) && (!i_status))
xerr_errx(1, "Status value not specified.");
if ((mode == MODE_SET_LOCATION) && (!u_loc))
xerr_errx(1, "Location value not specified.");
/* type */
if (i_type)
if (str_find8(otp_type_l, &u_type, i_type, 1, OTP_TYPE_MAX))
@ -334,7 +397,7 @@ int main (int argc, char **argv)
if (mode == MODE_ADD) {
printf("Adding user %s.\n", u_username);
if (otp_user_add(otpctx, u_username, u_key160, OTP_HOTP_KEY_SIZE,
if (otp_user_add(otpctx, u_username, u_loc, u_key160, OTP_HOTP_KEY_SIZE,
u_count, u_count_ceil, u_status, u_type, u_format, u_version))
xerr_errx(1, "otp_user_add(): failed.");
goto mode_done;
@ -343,10 +406,16 @@ int main (int argc, char **argv)
if (mode == MODE_REMOVE) {
printf("Removing user %s.\n", u_username);
if (otp_user_rm(otpctx, u_username) < 0)
xerr_errx(1, "ot_user_rm(): failed.");
xerr_errx(1, "otp_user_rm(): failed.");
goto mode_done;
} /* MODE_REMOVE */
if (mode == MODE_SEND_TOKEN) {
if (otp_user_send_token(otpctx, u_username, service) < 0)
xerr_errx(1, "otp_user_send_token(): failed.");
goto mode_done;
} /* MODE_SEND_TOKEN */
/*
* modes requiring open and get of user record:
*/
@ -355,6 +424,7 @@ int main (int argc, char **argv)
(mode == MODE_LIST_SC) ||
(mode == MODE_SET_COUNT) ||
(mode == MODE_SET_COUNT_CEIL) ||
(mode == MODE_SET_LOCATION) ||
(mode == MODE_SET_FLAGS) ||
(mode == MODE_SET_FORMAT) ||
(mode == MODE_SET_STATUS) ||
@ -408,6 +478,9 @@ int main (int argc, char **argv)
for (count_offset = 0; count_offset < window; ++count_offset) {
if (u_count_set == 1)
ou.count = u_count;
if (otp_urec_crsp(otpctx, &ou, count_offset, crsp_tmp, 11) < 0)
xerr_errx(1, "otp_urec_crsp(): failed.");
@ -422,6 +495,7 @@ int main (int argc, char **argv)
if ((mode == MODE_SET_COUNT) ||
(mode == MODE_SET_COUNT_CEIL) ||
(mode == MODE_SET_FLAGS) ||
(mode == MODE_SET_LOCATION) ||
(mode == MODE_SET_FORMAT) ||
(mode == MODE_SET_STATUS) ||
(mode == MODE_SET_TYPE)) {
@ -438,6 +512,10 @@ int main (int argc, char **argv)
ou.status = u_status;
else if (mode == MODE_SET_TYPE)
ou.type = u_type;
else if (mode == MODE_SET_LOCATION) {
strncpy(ou.loc, u_loc, sizeof(ou.loc));
ou.loc[sizeof(ou.loc)-1] = 0;
}
if (otp_urec_put(otpctx, &ou) < 0)
xerr_errx(1, "otp_urec_put(): failed.");
@ -473,15 +551,17 @@ mode_done:
void help(void)
{
extern char *ootp_version;
int i;
fprintf(stderr, "otp-control [-?hnv] [-c count] [-C count_ceil] [-f format] [-F flags]\n");
fprintf(stderr, " [-H sc_hostname] [-I sc_index] [-k key] [-m command_mode]\n");
fprintf(stderr, " [-o otbdb_pathname] [-s status] [-S sc_flags] [ -t type]\n");
fprintf(stderr, " [-u username] [-w window]\n");
fprintf(stderr, " -h : help\n");
fprintf(stderr, " -n : create database\n");
fprintf(stderr, " -v : enable verbose output\n\n");
fprintf(stderr, "otp-control [-?hnv] [-c count] [-C count_ceil] [-f format] [-F flag]\n");
fprintf(stderr, " [-H sc_hostname] [-I sc_index] [-k key] [-l location]\n");
fprintf(stderr, " [-m command_mode] [-o otbdb_pathname] [-s status] [-S sc_flags] [-V service]\n");
fprintf(stderr, " [-t type] [-u username] [-w window]\n");
fprintf(stderr, " -h : help\n");
fprintf(stderr, " -n : create database\n");
fprintf(stderr, " -v : enable verbose output\n");
fprintf(stderr, " --version : build version\n\n");
fprintf(stderr, " sc_flags : 0=CHALLENGE 1=READERKEY\n");
fprintf(stderr, " flags : ");
@ -515,6 +595,7 @@ void help(void)
fprintf(stderr, " list-sc - List user record (SC friendly)\n");
fprintf(stderr, " load - ASCII load user record(s)\n");
fprintf(stderr, " remove - Remove user\n");
fprintf(stderr, " send-token - Send token to user\n");
fprintf(stderr, " set-count - Set user count\n");
fprintf(stderr, " set-count-ceil - Set user count ceiling\n");
fprintf(stderr, " set-flags - Set user flags\n");
@ -522,6 +603,7 @@ void help(void)
fprintf(stderr, " set-status - Set user status\n");
fprintf(stderr, " set-type - Set user OTP type\n");
fprintf(stderr, " test - Test user\n");
printf("%s\n", ootp_version);
}
int get_random(char *dev, unsigned char *entropy, int bits)
@ -548,3 +630,4 @@ int get_random(char *dev, unsigned char *entropy, int bits)
return 0;
} /* get_random */

View file

@ -1,4 +1,4 @@
# $Id: Makefile 13 2009-11-26 16:37:03Z maf $
# $Id: Makefile 133 2010-06-15 14:30:14Z maf $
what:
@echo
@ -22,22 +22,28 @@ INSTALL=install -c -m0755
.c.o:; $(CC) $(CFLAGS) -c $*.c -o $*.o
OBJS = ../common/xerr.o ../common/str.o ../common/otplib.o ../common/ffdb.o
BIN = otp-ov-plugin
COBJS = ../common/xerr.o ../common/str.o ../common/otplib.o ../common/ffdb.o
OBJS = version.o ${BIN}.o
BINS = otp-ov-plugin
BINDIR=/usr/local/ootp/bin
all: otp-ov-plugin.c ${OBJS} ${BINS}
all: version ${COBJS} ${OBJS} ${BIN}
version:
rm -f version.c; ../build/version ../VERSION ${BIN} > version.c
version.c:
install:
mkdir -p ${BINDIR}
${INSTALL} ${BINS} ${BINDIR}
${INSTALL} ${BIN} ${BINDIR}
@echo files installed in ${BINDIR}
clean:
/bin/rm -f ${BINS} otp-ov-plugin.o
/bin/rm -f ${BIN} ${OBJS} version.c
otp-ov-plugin: ${OBJS} otp-ov-plugin.o
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o otp-ov-plugin ${OBJS} otp-ov-plugin.o $(LIBS)
${BIN}: ${COBJS} ${OBJS}
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o ${BIN} ${COBJS} ${OBJS} $(LIBS)

View file

@ -24,14 +24,15 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: otp-ov-plugin.c 50 2009-12-15 01:37:19Z maf $
* $Id: otp-ov-plugin.c 177 2011-05-16 02:37:28Z maf $
*/
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/errno.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/errno.h>
#include "ffdb.h"
#include "otplib.h"
#include "xerr.h"
@ -40,10 +41,24 @@ void help(void);
int main (int argc, char **argv)
{
extern char *ootp_version;
struct otp_ctx *otpctx;
struct otp_user ou;
u_long tmpul;
char *otpdb_fname, *username, *pass, *endptr;
int db_flags, i, r, ret, otp_window;
char *otpdb_fname, *username, *pass, *endptr, *service;
int db_flags, i, r, ret, otp_window, opt_version, otp_allow_unknown;
struct option longopts[] = {
{ "otp-allow-unknown-user", 0, (void*)0L, 'u'},
{ "help", 0, (void*)0L, 'h'},
{ "help", 0, (void*)0L, '?'},
{ "otp-db", 1, (void*)0L, 'o'},
{ "verbose", 0, (void*)0L, 'v'},
{ "service-name", 0, (void*)0L, 'V'},
{ "otp-challenge-window", 1, (void*)0L, 'w'},
{ "version", 0, &opt_version, 1},
{ 0, 0, 0, 0},
};
/* init xerr */
xerr_setid(argv[0]);
@ -51,12 +66,17 @@ int main (int argc, char **argv)
otpdb_fname = OTP_DB_FNAME;
db_flags = 0;
otp_window = OTP_WINDOW_DEFAULT;
opt_version = 0;
otp_allow_unknown = 0;
service = "otp-openvpn";
bzero(&ou, sizeof(ou));
ret = -1; /* fail */
while ((i = getopt(argc, argv, "h?o:vw:")) != -1) {
while ((i = getopt_long(argc, argv, "h?o:uvV:w:", longopts,
(int*)0L)) != -1) {
switch (i) {
switch (i) {
case 'h':
case '?':
help();
@ -66,10 +86,18 @@ int main (int argc, char **argv)
otpdb_fname = optarg;
break;
case 'u':
otp_allow_unknown = 1;
break;
case 'v':
db_flags |= OTP_DB_VERBOSE;
break;
case 'V':
service = optarg;
break;
case 'w':
tmpul = strtoul(optarg, &endptr, 0);
if (*endptr)
@ -79,9 +107,16 @@ int main (int argc, char **argv)
otp_window = tmpul;
break;
case 0:
if (opt_version) {
printf("%s\n", ootp_version);
exit(0);
}
break;
default:
help();
exit(1);
xerr_errx(1, "getopt_long(): fatal.");
break; /* not reached */
} /* switch */
@ -99,8 +134,39 @@ int main (int argc, char **argv)
if ((r = otp_user_exists(otpctx, username)) < 0)
xerr_errx(1, "otp_user_exists(): failed.");
if ((r == 1) && (otp_allow_unknown == 0)) {
xerr_info("OTP_AUTH_FAIL via otp_user_exists() allow_unknown=0");
ret = 1;
goto done;
}
if ((r == 1) && (otp_allow_unknown == 1)) {
xerr_info("OTP_AUTH_PASS via unknown user and allow_unknown=1");
ret = 0;
goto done;
}
if (r != 0)
xerr_errx(1, "User %s does not exist in otp database.", username);
if (otp_urec_open(otpctx, username, &ou, O_RDONLY,
FFDB_OP_LOCK_EX) < 0)
xerr_errx(1, "otp_urec_open(%s): failed.", username);
if (otp_urec_get(otpctx, &ou) < 0)
xerr_errx(1, "otp_urec_get(): failed.");
if (otp_urec_close(otpctx, &ou) < 0)
xerr_errx(1, "otp_urec_close(): failed.");
if (ou.flags & OTP_FLAGS_SEND_TOKEN) {
if (otp_user_send_token(otpctx, username, service) < 0)
xerr_warnx("otp_user_send_token(): failed.");
}
if ((r = otp_user_auth(otpctx, username, pass, otp_window)) < 0)
xerr_errx(1, "otp_user_auth(): failed.");
@ -110,15 +176,15 @@ int main (int argc, char **argv)
/* convert otp auth status to openvpn auth return code space */
if (r == OTP_AUTH_PASS) {
if (db_flags & OTP_DB_VERBOSE)
xerr_info("OTP_AUTH_PASS");
xerr_info("OTP_AUTH_PASS");
ret = 0;
} else {
if (db_flags & OTP_DB_VERBOSE)
xerr_info("OTP_AUTH_FAIL");
xerr_info("OTP_AUTH_FAIL");
ret = 1;
}
done:
return ret;
} /* main.c */

View file

@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: pam_otp.c 56 2009-12-17 02:08:05Z maf $
* $Id: pam_otp.c 168 2011-05-11 04:03:38Z maf $
*/
#include <stdio.h>
@ -79,9 +79,10 @@ struct opts {
int expose_account;
int display_count;
int allow_inactive;
int require_db_entry;
int allow_unknown;
int otp_window;
char *otpdb_fname;
char *service;
};
void load_opts(struct opts *opts, int argc, const char **argv);
@ -99,10 +100,11 @@ int pam_sm_authenticate(pam_handle_t *ph, int flags, int argc,
struct opts opts;
int r, ret, otpdb_flags;
const char *user;
char message[64];
char message[64], *cs;
ppam_msg = &pam_msg;
bzero(&pam_msg, sizeof (pam_msg));
bzero(&opts, sizeof opts);
pam_conv = 0L;
pam_resp = 0L;
ret = PAM_SERVICE_ERR;
@ -146,15 +148,27 @@ int pam_sm_authenticate(pam_handle_t *ph, int flags, int argc,
*
*/
if (r == 1) {
if (!opts.require_db_entry)
if (opts.allow_unknown) {
ret = PAM_SUCCESS;
else
xerr_info("%s: user=%s pass otp_user_exists() allow_unknown=1",
pam_strerror(ph, ret), user);
} else {
ret = PAM_AUTH_ERR;
xerr_info("%s: user=%s not in OTP db", pam_strerror(ph, ret), user);
xerr_info("%s: user=%s via otp_user_exists() allow_unknown=0",
pam_strerror(ph, ret), user);
}
goto cleanup;
}
/*
* unknown response from otp_user_exists()
*/
if (r != 0) {
xerr_warnx("otp_user_exists() unknown response r=%d", r);
ret = PAM_SERVICE_ERR;
goto cleanup;
}
/* get otp user record */
if (otp_urec_open(otpctx, (char*)user, &ou, O_RDONLY, FFDB_OP_LOCK_EX) < 0) {
xerr_warnx("otp_urec_open(%s): failed.", user);
ret = PAM_SERVICE_ERR;
@ -212,11 +226,25 @@ int pam_sm_authenticate(pam_handle_t *ph, int flags, int argc,
pam_msg.msg_style = PAM_PROMPT_ECHO_ON;
pam_msg.msg = (char *)&message;
/* send token to user? */
if (ou.flags & OTP_FLAGS_SEND_TOKEN) {
cs = "HOTP Sent";
if (otp_user_send_token(otpctx, (char*)user, opts.service) < 0)
xerr_warnx("otp_user_send_token(): failed.");
} else {
cs = "HOTP Challenge";
} /* OTP_FLAGS_SEND_TOKEN */
/* prompt for challenge with optional count */
if (opts.display_count || (ou.flags & OTP_FLAGS_DSPCNT))
sprintf(message, "HOTP Challenge (%" PRIu64 "): ", ou.count);
snprintf(message, sizeof(message), "%s (%" PRIu64 "): ", cs, ou.count);
else
sprintf(message, "HOTP Challenge: ");
snprintf(message, sizeof(message), "%s: ", cs);
/* use application conversation function to ask for challenge */
if (pam_conv->conv(1, &ppam_msg, &pam_resp, pam_conv->appdata_ptr)
@ -331,6 +359,7 @@ void load_opts(struct opts *opts, int argc, const char **argv)
bzero(opts, sizeof *opts);
opts->otpdb_fname = OTP_DB_FNAME;
opts->otp_window = OTP_WINDOW_DEFAULT;
opts->service = "pam";
/* foreach argument */
while (argc--) {
@ -348,9 +377,13 @@ void load_opts(struct opts *opts, int argc, const char **argv)
} else if (!strcmp(*argv, "allow_inactive")) {
opts->allow_inactive = 1;
} else if (!strcmp(*argv, "require_db_entry")) {
opts->require_db_entry = 1;
opts->allow_unknown = 0;
} else if (!strcmp(*argv, "allown_unknown")) {
opts->allow_unknown = 1;
} else if (!strncmp(*argv, "otpdb=", 6)) {
opts->otpdb_fname=(char*)(*argv)+6;
} else if (!strncmp(*argv, "service=", 8)) {
opts->service=(char*)(*argv)+8;
} else if (!strncmp(*argv, "window=", 7)) {
tmpul = strtoul(optarg, &endptr, 0);
if (*endptr)
@ -366,10 +399,10 @@ void load_opts(struct opts *opts, int argc, const char **argv)
}
if (opts->debug) {
xerr_info("use_first_pass=%d, try_first_pass=%d, expose_account=%d, display_count=%d, allow_inactive=%d, require_db_entry=%d, otpdb=%s",
xerr_info("use_first_pass=%d, try_first_pass=%d, expose_account=%d, display_count=%d, allow_inactive=%d, allow_unknown=%d, otpdb=%s service=%s",
opts->use_first_pass, opts->use_first_pass, opts->expose_account,
opts->display_count, opts->allow_inactive, opts->require_db_entry,
opts->otpdb_fname);
opts->display_count, opts->allow_inactive, opts->allow_unknown,
opts->otpdb_fname, opts->service);
}
} /* load_opts */

View file

@ -1,4 +1,4 @@
# $Id: Makefile 13 2009-11-26 16:37:03Z maf $
# $Id: Makefile 130 2010-06-15 14:26:10Z maf $
what:
@echo
@ -25,22 +25,28 @@ INSTALL=install -c -m0755
.c.o:; $(CC) $(CFLAGS) -c $*.c -o $*.o
OBJS = ../common/xerr.o ../common/str.o ../common/acr30.o ../common/scr.o ../common/sccmd.o
BIN = otp-sca
COBJS = ../common/xerr.o ../common/str.o ../common/acr30.o ../common/scr.o ../common/sccmd.o
OBJS = version.o ${BIN}.o
BINS = otp-sca
BINDIR=/usr/local/ootp/bin
all: otp-sca.c ${OBJS} ${BINS}
all: version ${COBJS} ${OBJS} ${BIN}
version:
rm -f version.c; ../build/version ../VERSION ${BIN} > version.c
version.c:
install:
mkdir -p ${BINDIR}
${INSTALL} ${BINS} ${BINDIR}
${INSTALL} ${BIN} ${BINDIR}
@echo files installed in ${BINDIR}
clean:
/bin/rm -f ${BINS} otp-sca.o
/bin/rm -f ${BIN} ${OBJS} version.c
otp-sca: ${OBJS} otp-sca.o
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o otp-sca ${OBJS} otp-sca.o $(LIBS)
${BIN}: ${OBJS} ${COBJS}
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o ${BIN} ${COBJS} ${OBJS} $(LIBS)

View file

@ -24,13 +24,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: otp-sca.c 88 2009-12-28 00:12:01Z maf $
* $Id: otp-sca.c 144 2010-10-19 02:05:40Z maf $
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <getopt.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
@ -115,9 +116,10 @@ static int debug;
/* XXX many of these +1 LEN's are not necessary */
int main(int argc, char **argv)
{
extern char *ootp_version;
struct scr_ctx *scrctx;
int i, j, k, r, mode, sc_idx_set, j_start, j_end, done, sc_idx_tmp, opt_mod;
int no_PIN, list_readers;
int no_PIN, list_readers, opt_version;
uint32_t tmp_count, tmp_cap, tmp32u;
uint64_t tmp64u;
char sc_hostname[SC_HOSTNAME_LEN+1], sc_PIN[SC_PIN_LEN+1];
@ -136,6 +138,25 @@ int main(int argc, char **argv)
char *adminkey_hex160_fname, *endptr, *err_msg, *username, *reader;
char *readerkey_hex40_fname;
struct option longopts[] = {
{ "sc-admin-key", 1, (void*)0L, 'a'},
{ "sc-count", 1, (void*)0L, 'c'},
{ "debug", 1, (void*)0L, 'd'},
{ "help", 0, (void*)0L, 'h'},
{ "help", 0, (void*)0L, '?'},
{ "sc-index", 1, (void*)0L, 'i'},
{ "list-readers", 0, (void*)0L, 'l'},
{ "sc-command", 1, (void*)0L, 'm'},
{ "sc-command-modifier", 1, (void*)0L, 'M'},
{ "no-pin", 0, (void*)0L, 'p'},
{ "reader", 1, (void*)0L, 'r'},
{ "sc-reader-key", 1, (void*)0L, 'R'},
{ "sc-username", 1, (void*)0L, 'u'},
{ "sc-version", 1, (void*)0L, 'v'},
{ "version", 0, &opt_version, 1},
{ 0, 0, 0, 0},
};
/* init xerr */
xerr_setid(argv[0]);
@ -144,6 +165,7 @@ int main(int argc, char **argv)
mode = 0;
opt_mod = 0;
sc_idx_set = 0;
opt_version = 0;
adminkey_hex160_fname = (char*)0L;
readerkey_hex40_fname = (char*)0L;
sc_fv = 5;
@ -173,7 +195,8 @@ int main(int argc, char **argv)
bcopy(SC_PIN_DEFAULT, sc_newPIN, SC_PIN_LEN);
bcopy(SC_ADMINKEY_DEFAULT, sc_adminkey, SC_ADMINKEY_LEN);
while ((i = getopt(argc, argv, "a:c:d:h?i:lm:M:pr:R:u:v:")) != -1) {
while ((i = getopt_long(argc, argv, "a:c:d:h?i:lm:M:pr:R:u:v:", longopts,
(int*)0L)) != -1) {
switch (i) {
@ -304,9 +327,18 @@ int main(int argc, char **argv)
xerr_errx(1, "strtoul(%s): failed at %c.", optarg, *endptr);
break;
case 0:
if (opt_version) {
printf("%s\n", ootp_version);
exit(0);
}
default:
xerr_errx(1, "getopt_long(): fatal.");
} /* switch */
} /* while getopt() */
} /* while getopt_long() */
/* work to do? */
if (!mode && !list_readers) {
@ -579,6 +611,9 @@ int main(int argc, char **argv)
if (tmp_cap & SC_CLEARALL_CAP)
printf(" %s", SC_CLEARALL_STR);
if (tmp_cap & SC_SETREADERKEY_CAP)
printf(" %s", SC_GETCAPABILITIES_STR);
printf("\n");
} else if (r == 1) {

8
otp-sca/rfc.card Normal file
View file

@ -0,0 +1,8 @@
00:00000000:5246432d4845583430000000:3132333435363738393031323334353637383930
01:00000000:5246432d4845583430000080:3132333435363738393031323334353637383930
02:00000000:5246C32d4445432e36008000:3132333435363738393031323334353637383930
03:00000000:5246C32d4445432e37008080:3132333435363738393031323334353637383930
04:00000000:5246C32d4445432e38800000:3132333435363738393031323334353637383930
05:00000000:5246C32d4445432e39800080:3132333435363738393031323334353637383930
06:00000000:5246C32d4445432e41808000:3132333435363738393031323334353637383930
07:00000000:5246432d4445583430808080:3132333435363738393031323334353637383930

View file

@ -1,4 +1,4 @@
# $Id: Makefile 13 2009-11-26 16:37:03Z maf $
# $Id: Makefile 131 2010-06-15 14:26:23Z maf $
what:
@echo
@ -25,22 +25,27 @@ INSTALL=install -c -m0755
.c.o:; $(CC) $(CFLAGS) -c $*.c -o $*.o
BIN = otp-sct
OBJS = ../common/xerr.o ../common/str.o ../common/acr30.o ../common/scr.o ../common/sccmd.o
BINS = otp-sct
COBJS = version.o ${BIN}.o
BINDIR=/usr/local/ootp/bin
all: otp-sct.c ${OBJS} ${BINS}
all: version ${OBJS} ${BIN}
version:
rm -f version.c; ../build/version ../VERSION ${BIN} > version.c
version.c:
install:
mkdir -p ${BINDIR}
${INSTALL} ${BINS} ${BINDIR}
${INSTALL} ${BIN} ${BINDIR}
@echo files installed in ${BINDIR}
clean:
/bin/rm -f ${BINS} otp-sct.o
/bin/rm -f ${BIN} otp-sct.o version.c
otp-sct: ${OBJS} otp-sct.o
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o otp-sct ${OBJS} otp-sct.o $(LIBS)
${BIN}: ${COBJS} ${OBJS}
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o ${BIN} ${OBJS} ${COBJS} $(LIBS)

View file

@ -24,13 +24,14 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: otp-sct.c 88 2009-12-28 00:12:01Z maf $
* $Id: otp-sct.c 131 2010-06-15 14:26:23Z maf $
*/
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/errno.h>
#include <getopt.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
@ -77,8 +78,9 @@ void help(void);
int main(int argc, char **argv)
{
extern char *ootp_version;
struct scr_ctx *scrctx;
int i, j, k, r, sc_idx_set, sc_idx_tmp, j_start, j_end;
int i, j, k, r, sc_idx_set, sc_idx_tmp, j_start, j_end, opt_version;
int reset_pin, list_readers, list_version, get_hotp_version, list_hostnames;
uint32_t tmp_count, tmp32u;
uint64_t tmp64u;
@ -90,9 +92,27 @@ int main(int argc, char **argv)
u_char sc_fv;
char *reader, *endptr, *err_msg;
struct option longopts[] = {
{ "sc-get-hotp-v1", 0, (void*)0L, '1'},
{ "sc-count", 1, (void*)0L, 'c'},
{ "debug", 1, (void*)0L, 'd'},
{ "help", 0, (void*)0L, 'h'},
{ "help", 0, (void*)0L, '?'},
{ "sc-index", 1, (void*)0L, 'i'},
{ "list-readers", 0, (void*)0L, 'l'},
{ "sc-list-hostnames", 0, (void*)0L, 'L'},
{ "sc-reset-pin", 0, (void*)0L, 'p'},
{ "reader", 1, (void*)0L, 'r'},
{ "sc-version", 1, (void*)0L, 'v'},
{ "sc-list-version", 0, (void*)0L, 'V'},
{ "version", 0, &opt_version, 1},
{ 0, 0, 0, 0},
};
/* init xerr */
xerr_setid(argv[0]);
opt_version = 0;
sc_fv = 5;
debug = 0;
sc_idx_set = 0;
@ -116,7 +136,8 @@ int main(int argc, char **argv)
bcopy(SC_PIN_DEFAULT, sc_pin, SC_PIN_LEN);
bcopy(SC_PIN_DEFAULT, sc_newpin, SC_PIN_LEN);
while ((i = getopt(argc, argv, "1c:d:hi:lLpr:v:V?")) != -1) {
while ((i = getopt_long(argc, argv, "1c:d:hi:lLpr:v:V?", longopts,
(int*)0L)) != -1) {
switch (i) {
@ -189,9 +210,18 @@ int main(int argc, char **argv)
list_version = 1;
break;
case 0:
if (opt_version) {
printf("%s\n", ootp_version);
exit(0);
}
default:
xerr_errx(1, "getopt_long(): fatal.");
} /* switch */
} /* while getopt() */
} /* while getopt_long() */
/* get pin */
if (!list_readers && !list_version) {

50
otp-tokend/Makefile Normal file
View file

@ -0,0 +1,50 @@
# $Id: Makefile 129 2010-06-15 14:25:43Z maf $
what:
@echo
@echo "make hardware-systype"
@echo
@echo "This Makefile knows about the following"
@echo
@echo i386-fbsd i386-linux i386-macosx
@echo
i386-fbsd:
@make CC="gcc" CFLAGS="-I../common -g -DHAVE_STRING_H -DHAVE_STRINGS_H -DDEBUG -Wall -std=c99 -pedantic" LIBS="-lcurl" all
i386-linux:
@make CC="gcc" CFLAGS="-I../common -g -DHAVE_STRING_H -DHAVE_STRINGS_H -DDEBUG -D_BSD_SOURCE -D_XOPEN_SOURCE -Wall -std=c99 -pedantic" LIBS="-lcurl " all
i386-macosx:
@make CC="gcc" CFLAGS="-I../common -g -DHAVE_STRING_H -DHAVE_STRINGS_H -DDEBUG -Wall -std=c99 -pedantic" LIBS="-lcurl" all
INSTALL=install -c -m0755
.c.o:; $(CC) $(CFLAGS) $(INC) -c $*.c -o $*.o
BIN = otp-tokend
COBJS = ../common/xerr.o
OBJS = version.o ${BIN}.o
LFLAGS = -L/usr/local/lib
INC = -I/usr/local/include
BINDIR=/usr/local/ootp/bin
all: version ${COBJS} ${OBJS} ${BIN}
version:
rm -f version.c; ../build/version ../VERSION ${BIN} > version.c
version.c:
install:
mkdir -p ${BINDIR}
${INSTALL} ${BIN} ${BINDIR}
@echo files installed in ${BINDIR}
clean:
/bin/rm -f ${BIN} ${OBJS} version.c
${BIN}: ${COBJS} ${OBJS}
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o ${BIN} ${COBJS} ${OBJS} $(LIBS)

360
otp-tokend/otp-tokend.c Normal file
View file

@ -0,0 +1,360 @@
#include <errno.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/types.h>
#include <stdio.h>
#include <netdb.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <curl/curl.h>
#include <ctype.h>
#include "xerr.h"
#include "otplib.h"
/* XXX usage
* XXX man page
*/
static u_long scan_ip(char *s);
static void usage(void);
static int write_pidfile(char *fname);
#define NXT_FIELD(V1,V2)\
f = strsep(&c, "\n");\
if (!f) {\
xerr_warnx("parse rx_buf fail at %s", V1);\
continue;\
}\
V2 = c;\
size_t curl_write_cb(void *ptr, size_t size, size_t nmemb, void *userdata);
int main(int argc, char **argv)
{
extern char *ootp_version;
struct sockaddr_un rx_path;
CURL *curl;
char rx_buf[1024], *c, *f, *msg_svc, *msg_user, *msg_loc, *msg_token;
char msg_buf[1024], post_buf[1024], *msg_ue, *loc_ue, *rx_pathname;
char buf[1024], *pid_fname, *url;
int rx_sock, len, verbose, opt_version, daemon_mode, buf_l, i;
struct option longopts[] = {
{ "bind-path", 1, (void*)0L, 'b'},
{ "disable-daemon-mode", 1, (void*)0L, 'D'},
{ "help", 0, (void*)0L, 'h'},
{ "help", 0, (void*)0L, '?'},
{ "pidfile", 1, (void*)0L, 'P'},
{ "url", 1, (void*)0L, 'u'},
{ "verbose", 0, (void*)0L, 'v'},
{ "version", 1, &opt_version, 1},
{ 0, 0, 0, 0},
};
daemon_mode = 1;
opt_version = 0;
pid_fname = (char*)0L;
url = (char*)0L;
verbose = 0;
xerr_setid(argv[0]);
rx_pathname = OTP_SEND_TOKEN_PATHNAME;
while ((i = getopt_long(argc, argv, "b:Dh?P:u:v", longopts,
(int*)0L)) != -1) {
switch (i) {
case 'b':
rx_pathname = optarg;
break;
case 'D':
daemon_mode = 0;
break;
case 'h':
case '?':
usage();
exit(0);
break;
case 'P':
pid_fname = optarg;
break;
case 'u':
url = optarg;
break;
case 'v':
++verbose;
break;
case 0:
if (opt_version) {
printf("%s\n", ootp_version);
exit(0);
}
default:
xerr_errx(1, "getopt_long(): fatal.");
} /* switch */
} /* while getopt_long() */
if (!url)
xerr_errx(1, "url required.");
if (daemon_mode) {
xerr_setsyslog2(1); /* use syslog for output */
/* run in the background */
if (daemon(0, 0) < 0)
xerr_err(1, "dameon()");
} /* daemon_mode */
buf_l = snprintf(buf, sizeof(buf), "tokend start:");
if (verbose > 1) {
for (i = 0; i < argc; ++i)
buf_l += snprintf(buf+buf_l, sizeof(buf)-buf_l, " %s", argv[i]);
}
xerr_info(buf);
bzero(&rx_path, sizeof (rx_path));
rx_path.sun_family = AF_UNIX;
if (strlen(rx_pathname) >= sizeof(rx_path.sun_path))
xerr_errx(1, "rx_pathname too long.");
strncpy(rx_path.sun_path, rx_pathname, sizeof(rx_path.sun_path));
/* construct pid file name */
if (!pid_fname) {
if (strcmp(rx_pathname, OTP_SEND_TOKEN_PATHNAME)) {
snprintf(buf, sizeof(buf), "/var/run/otp-tokend.pid.%s",
rx_pathname);
} else {
snprintf(buf, sizeof(buf), "/var/run/otp-tokend.pid");
}
pid_fname = (char*)&buf;
}
/* write out pidfile */
if (write_pidfile(pid_fname) < 0)
xerr_errx(1, "write_pidfile(%s): fatal", buf);
if (!(curl = curl_easy_init()))
xerr_errx(1, "curl_easy_init()");
if ((rx_sock = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0)
xerr_err(1, "socket()");
/* fail silently */
umask(077);
unlink(rx_pathname);
if (bind(rx_sock, (struct sockaddr*)&rx_path, sizeof(rx_path)) < 0)
xerr_err(1, "bind(%s)", rx_pathname);
if (verbose > 1)
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
if (curl_easy_setopt(curl, CURLOPT_URL, url) != CURLE_OK)
xerr_errx(1, "curl_easy_setopt(url): failed.");
if (curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,
&curl_write_cb) != CURLE_OK)
xerr_errx(1, "curl_easy_setopt(CURLOPT_WRITEFUNCTION): failed.");
while (1) {
if ((len = recv(rx_sock, &rx_buf, sizeof(rx_buf), 0)) < 0)
xerr_err(1, "recv()");
if (len == 0) {
xerr_warnx("rx_buf empty.");
continue;
}
if (rx_buf[len - 1] != 0) {
xerr_warnx("recv(): rx_buf not null terminated, skipping.");
continue;
}
c = rx_buf;
msg_svc = rx_buf;
NXT_FIELD("msg_user", msg_user);
NXT_FIELD("msg_loc", msg_loc);
NXT_FIELD("msg_token", msg_token);
for (c = msg_token; *c; ++c)
if (*c == '\n')
*c = 0;
snprintf(msg_buf, sizeof(msg_buf), "%s: %s", msg_svc, msg_token);
if (!(msg_ue = curl_escape(msg_buf, 0))) {
xerr_warnx("curl_escape(msg_buf): failed.");
continue;
}
if (!(loc_ue = curl_escape(msg_loc, 0))) {
xerr_warnx("curl_escape(msg_loc): failed.");
free(msg_ue);
continue;
}
snprintf(post_buf, sizeof(post_buf), "to=%s&msg=%s", loc_ue, msg_ue);
if (curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_buf) != CURLE_OK)
xerr_errx(1, "curl_easy_setopt(CURLOPT_POSTFIELDS, %s): failed.",
post_buf);
if (curl_easy_perform(curl) != CURLE_OK)
xerr_warnx("1, curl_easy_perform(): failed.");
if (verbose > 1)
xerr_info("msg_buf=%s", msg_buf);
}
}
size_t curl_write_cb(void *ptr, size_t size, size_t nmemb, void *userdata)
{
char *c;
c = malloc((size*nmemb)+1);
bcopy(ptr, c, size*nmemb);
c[size*nmemb] = 0;
xerr_info(c);
free(c);
return size*nmemb;
}
void usage(void)
{
}
/*
* function: write_pidfile()
*
* Store proces ID in ASII to fname.
*
* returns: < 0 : fail
* 0 : success
*/
int write_pidfile(char *fname)
{
int fd, buf_l;
char buf[512];
buf_l = snprintf(buf, sizeof(buf), "%lu\n", (unsigned long)getpid());
if ((fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0 ) {
xerr_warn("open(%s)", fname);
return -1;
}
if (write(fd, buf, buf_l) < 0) {
xerr_warn("write(%s)", fname);
close (fd);
return -1;
}
return (close(fd));
} /* write_pidfile */
/*
* function: scan_ip
*
* IP address in string S is converted to a u_long
* (borrowed from tcpdump)
*
* left shift any partial dotted quads, ie 10 is 0x0a000000 not 0x0a
* so scan_ip_prefix() works for standard prefix notation, ie 10/8
*/
u_long scan_ip(char *s)
{
struct hostent *he;
struct in_addr *ina;
u_long addr = 0;
uint n;
int dns, shift;
char *t;
/* if there is anything ascii in here, this may be a hostname */
for (dns = 0, t = s; *t; ++t) {
if (islower((int)*t) || isupper((int)*t)) {
dns = 1;
break;
}
}
if (dns) {
if (!(he = gethostbyname(s)))
goto numeric;
if (he->h_addrtype != AF_INET)
goto numeric;
if (he->h_length != sizeof (uint32_t))
goto numeric;
ina = (struct in_addr*)*he->h_addr_list;
return (ntohl(ina->s_addr));
} /* dns */
shift = 0;
numeric:
while (1) {
/* n is the nibble */
n = 0;
/* nibble's are . bounded */
while (*s && (*s != '.') && (*s != ' ') && (*s != '\t'))
n = n * 10 + *s++ - '0';
/* shift in the nibble */
addr <<=8;
addr |= n & 0xff;
++shift;
/* return on end of string */
if ((!*s) || (*s == ' ') || (*s == '\t'))
goto ndone;
/* skip the . */
++s;
} /* forever */
ndone:
for (; shift < 4; ++shift)
addr <<=8;
return addr;
} /* scan_ip */

View file

@ -1,6 +1,6 @@
#!/bin/sh -e
# $Id: otpdb2sc 40 2009-12-01 16:28:53Z maf $
# $Id: otpdb2sc 138 2010-06-15 15:34:14Z maf $
OTPCONTROL="otp-control"
DDIR="/priv/HOTP"
@ -17,7 +17,7 @@ fi
if [ "X$3" = "X" ]; then
FLAGS=""
else
FLAGS="-F$3"
FLAGS="-S$3"
fi
if [ ! -e $OTPDB ]; then
@ -26,7 +26,7 @@ fi
touch $CARDF
idx=`wc -l $CARDF | awk '{print $1}`
idx=`wc -l $CARDF | awk '{print $1}'`
idx2=$idx
if [ $idx -lt 10 ]; then
idx2="0$idx"

View file

@ -1,9 +1,9 @@
# $Id: Makefile 13 2009-11-26 16:37:03Z maf $
# $Id: Makefile 101 2009-12-28 03:04:32Z maf $
INSTALLI=install -c -m0644
INSTALL=install -c -m0755
IMGS = spyrus1.3.hex oar.ee oar.str
IMGS = spyrus1.4.hex oar.ee oar.str
BINS = str2ee
DOCS = eeprom-map.txt oar.str

View file

@ -1,4 +1,4 @@
# $Id: Makefile 35 2009-11-30 21:49:59Z maf $
# $Id: Makefile 155 2011-04-06 02:25:43Z maf $
what:
@echo
@ -10,34 +10,39 @@ what:
@echo
i386-fbsd:
@make CC="gcc" CFLAGS="-I../common -g -DOOTP_ENABLE -DHAVE_STRING_H -DHAVE_STRINGS_H -DDEBUG -Wall -std=c99 -pedantic" LIBS="-lssl -lcrypt" all
@make CC="gcc" CFLAGS="-I../common -g -DOOTP_ENABLE -DHAVE_STRING_H -DHAVE_STRINGS_H -DDEBUG -Wall -std=c99 -pedantic" LIBS="-lssl -lcrypt -lpam" all
i386-linux:
@make CC="gcc" CFLAGS="-I../common -g -DOOTP_ENABLE -DHAVE_STRING_H -DHAVE_STRINGS_H -DDEBUG -D_BSD_SOURCE -D_XOPEN_SOURCE -Wall -std=c99 -pedantic" LIBS="-lssl -lcrypt" all
@make CC="gcc" CFLAGS="-I../common -g -DOOTP_ENABLE -DHAVE_STRING_H -DHAVE_STRINGS_H -DDEBUG -D_BSD_SOURCE -D_XOPEN_SOURCE -Wall -std=c99 -pedantic" LIBS="-lssl -lcrypt -lpam" all
i386-macosx:
@make CC="gcc" CFLAGS="-I../common -g -DOOTP_ENABLE -DHAVE_STRING_H -DHAVE_STRINGS_H -DDEBUG -Wall -std=c99 -pedantic" LIBS="-lssl -lcrypto" all
@make CC="gcc" CFLAGS="-I../common -g -DOOTP_ENABLE -DHAVE_STRING_H -DHAVE_STRINGS_H -DDEBUG -Wall -std=c99 -pedantic" LIBS="-lssl -lcrypto -lpam" all
INSTALL=install -c -m0755
.c.o:; $(CC) $(CFLAGS) -c $*.c -o $*.o
OBJS = pw.o rad.o ../common/xerr.o ../common/str.o ../common/otplib.o ../common/ffdb.o
BINS = urd
BIN = urd
COBJS = ../common/xerr.o ../common/str.o ../common/otplib.o ../common/ffdb.o
OBJS = version.o ${BIN}.o pw.o rad.o fileio.o
BINDIR=/usr/local/ootp/bin
all: pw.c rad.c urd.c ${OBJS} ${BINS}
all: version ${COBJS} ${OBJS} ${BIN}
version:
rm -f version.c; ../build/version ../VERSION ${BIN} > version.c
version.c:
install:
mkdir -p ${BINDIR}
${INSTALL} ${BINS} ${BINDIR}
${INSTALL} ${BIN} ${BINDIR}
@echo files installed in ${BINDIR}
clean:
/bin/rm -f ${BINS} urd.o pw.o rad.o
/bin/rm -f ${BIN} ${COBJS}
urd: ${OBJS} urd.o
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o urd ${OBJS} urd.o $(LIBS)
urd: ${COBJS} ${OBJS}
$(CC) $(CFLAGS) $(LFLAGS) $(INC) -o ${BIN} ${OBJS} ${COBJS} $(LIBS)

67
urd/fileio.c Normal file
View file

@ -0,0 +1,67 @@
#include "fileio.h"
#include "xerr.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
/*
* load file into memory.
*/
char *file_load(char *fname)
{
struct stat sb;
char *buf;
int fd, ret, len;
ret = -1; /* fail */
buf = (char*)0L;
fd = -1; /* invalid */
/* open file */
if ((fd = open(fname, O_RDONLY, 0)) < 0) {
xerr_warn("open(%s)", fname);
goto file_load_out;
}
/* load metadata */
if (fstat(fd, &sb) < 0) {
xerr_warn("stat(%s)", fname);
goto file_load_out;
}
/* allocate storage for file contents + null */
if (!(buf = malloc(sb.st_size+1))) {
xerr_warn("malloc(%d)", (int)sb.st_size+1);
goto file_load_out;
}
/* read file contents */
if ((len = read(fd, buf, sb.st_size)) < 0) {
xerr_warn("read(%s)", fname);
goto file_load_out;
}
/* null terminate */
buf[sb.st_size] = 0;
if (len != sb.st_size) {
xerr_warnx("short read(%s)", fname);
goto file_load_out;
}
ret = 0; /* success */
file_load_out:
if (fd != -1)
close(fd);
if ((ret == -1) && buf) {
free(buf);
buf = (char*)0L;
}
return buf;
} /* file_load */

4
urd/fileio.h Normal file
View file

@ -0,0 +1,4 @@
char *file_load(char *fname);

557
urd/pw.c
View file

@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: pw.c 13 2009-11-26 16:37:03Z maf $
* $Id: pw.c 155 2011-04-06 02:25:43Z maf $
*/
@ -33,6 +33,7 @@
#include <inttypes.h>
#include <stdlib.h>
#include <unistd.h>
#include <security/pam_appl.h>
#if HAVE_STRINGS_H
#include <strings.h>
@ -42,11 +43,13 @@
#endif
#include "pw.h"
#include "str.h"
#include "xerr.h"
#include "fileio.h"
/*
* Simple user authentication based on passwd file flat db with optional
* authorized users file. Database is cached in memory. stat(pw_fname)
* authorized users file. Database is cached in memory. stat(loc)
* is performed in pass_db_auth() to trigger a pass_db_load() when the
* filesystem database is newer than the memory cache. If this file
* does not exist the existing in memory database is used.
@ -67,7 +70,8 @@
*
* Usage:
* pass_db_ctx_new() : initialize context
* pass_db_ctx_free() : free resources associated with context
* pass_db_ctx_free() : free all resources associated with context
* pass_db_ctx_reset() : free username/password resources
* pass_db_load() : load and parse password file to memory
* pass_db_auth() : authenticate user_name/u_password pair.
* may call pass_db_load()
@ -78,6 +82,13 @@
*
*/
int pam_mem_conv (int pam_nmsg, const struct pam_message **pam_msgh,
struct pam_response **pam_resph, void *pam_app_data);
static int pam_auth(char *user_name, char *user_pass, char *svc_name);
static char *global_user_pass;
/*
* function: pass_db_ctx_new()
*
@ -91,7 +102,7 @@
* returns < 0 : fail
* 0 : success
*/
struct pass_db_ctx *pass_db_ctx_new(char *pw_fname, char *au_fname)
struct pass_db_ctx *pass_db_ctx_new(char *loc, char *au_fname, int type)
{
struct pass_db_ctx *pdbctx;
int i, ret;
@ -105,12 +116,14 @@ struct pass_db_ctx *pass_db_ctx_new(char *pw_fname, char *au_fname)
bzero(pdbctx, sizeof *pdbctx);
if (!(pdbctx->pw_fname = (char*)malloc(strlen(pw_fname)+1))) {
xerr_warn("malloc(%d)", strlen(pw_fname));
pdbctx->type = type;
if (!(pdbctx->loc = (char*)malloc(strlen(loc)+1))) {
xerr_warn("malloc(%d)", strlen(loc));
goto pass_db_ctx_new_out;
}
strcpy(pdbctx->pw_fname, pw_fname);
strcpy(pdbctx->loc, loc);
if (au_fname) {
@ -143,25 +156,52 @@ pass_db_ctx_new_out:
/*
* function: pass_db_ctx_free()
*
* Release resources in pass_db allocated by pass_db_init(). Must
* be called for each invocation of pass_db_init() to prevent resource
* Release resources in pass_db allocated by pass_db_ctx_new(). Must
* be called for each invocation of pass_db_ctx_new() to prevent resource
* leak.
*
*/
void pass_db_ctx_free(struct pass_db_ctx *pdbctx)
{
if (pdbctx) {
if (pdbctx->pw_fname);
free(pdbctx->pw_fname);
if (pdbctx->loc)
free(pdbctx->loc);
if (pdbctx->au_fname)
free(pdbctx->au_fname);
if (pdbctx->pw_entries);
if (pdbctx->pw_entries)
free(pdbctx->pw_entries);
bzero(pdbctx, sizeof (*pdbctx));
free(pdbctx);
}
} /* pass_db_ctx_free */
/*
* function: pass_db_ctx_reset()
*
* Release username/password resources from pass_db_ctx
*
*/
void pass_db_ctx_reset(struct pass_db_ctx *pdbctx)
{
int i;
if (pdbctx) {
if (pdbctx->debug)
xerr_info("pass_db_ctx_reset()");
if (pdbctx->pw_entries) {
bzero(pdbctx->pw_entries,
pdbctx->num_entries * sizeof (struct pass_db_entry));
pdbctx->num_entries = 0;
free(pdbctx->pw_entries);
}
for (i = 0; i < 1<<PASS_DB_HASH_BUCKET_BITS; ++i) {
SLIST_INIT(&pdbctx->bucket[i]);
}
}
} /* pass_db_ctx_reset */
/*
* function: pass_db_auth()
*
@ -170,11 +210,19 @@ void pass_db_ctx_free(struct pass_db_ctx *pdbctx)
* If au_fname was set in pass_db_ctx_new() the user must first exist
* in the authorized_users file else authentication will fail.
*
* Unix crypt() is used to compute a hash of u_pass for u_name
* in pass_db. If the hash matches the stored hash the user is
* authenticated.
* type=LOCAL
* Unix crypt() is used to compute a hash of u_pass for u_name
* in pass_db. If the hash matches the stored hash the user is
* authenticated.
* type=EX_LOCAL
* same as LOCAL, do not consult authorized_users
* type=PAM
* user must exist in local database, PAM is used for authentication
* type=EX_PAM
* PAM is used for authentication. Local password and authorized_users
* file is not consulted.
*
* reload pw_fname if the file is newer. If pw_fname does not
* reload loc if the file is newer. If loc does not
* exist, then ignore. This allows an updated password file to
* be linked into place avoiding race conditions of writing directly
* to the active file.
@ -188,23 +236,59 @@ int pass_db_auth(struct pass_db_ctx *pdbctx, char *u_name, char *u_pass)
struct pass_db_entry *pwe;
struct stat cur_sb;
char *crypt_result;
int ret;
int ret, need_reload;
ret = PASS_DB_AUTH_FAIL;
/* load current passwd file metadata */
if (stat(pdbctx->pw_fname, &cur_sb) < 0) {
goto skip_reload;
/* optimization when local database is not used */
if (pdbctx->type == PASS_DB_TYPE_EX_PAM)
goto skip_exists;
need_reload = 0;
/* check authorized users for update */
if ((pdbctx->type == PASS_DB_TYPE_LOCAL) ||
(pdbctx->type == PASS_DB_TYPE_PAM)) {
/* load current passwd file metadata */
if (stat(pdbctx->au_fname, &cur_sb) < 0) {
xerr_info("skipping reload, no %s", pdbctx->au_fname);
goto skip_reload;
}
/* passwd file updated? */
if (cur_sb.st_mtime != pdbctx->au_sb.st_mtime) {
xerr_info("reload on %s time", pdbctx->au_fname);
need_reload = 1;
}
} /* check for reload of au_fname */
/* check passwd file for updates */
if ((pdbctx->type == PASS_DB_TYPE_LOCAL) ||
(pdbctx->type == PASS_DB_TYPE_EX_LOCAL)) {
/* load current passwd file metadata */
if (stat(pdbctx->loc, &cur_sb) < 0) {
need_reload = 0;
xerr_info("skipping reload, no %s", pdbctx->loc);
goto skip_reload;
}
/* passwd file updated? */
if (cur_sb.st_mtime != pdbctx->pw_sb.st_mtime) {
xerr_info("reload on %s time", pdbctx->loc);
need_reload = 1;
}
}
/* passwd file updated? */
if (cur_sb.st_mtime != pdbctx->pw_sb.st_mtime) {
if (need_reload)
pdbctx->state = PASS_DB_STATE_RELOAD;
}
/* reload? then dispose of old state */
if (pdbctx->state == PASS_DB_STATE_RELOAD) {
pass_db_ctx_free(pdbctx);
pass_db_ctx_reset(pdbctx);
}
/* reload passwd database? */
@ -221,29 +305,49 @@ skip_reload:
/* hash lookup of user name */
if (!(pwe = pass_db_u_name_lookup(pdbctx, u_name, strlen(u_name)))) {
if (pdbctx->debug)
xerr_info("pass_db_auth(%s): no such user");
xerr_info("pass_db_auth(%s): no such user", u_name);
goto pass_db_auth_out;
}
if (pwe->status != PASS_DB_ENTRY_ACTIVE) {
if (pdbctx->debug)
xerr_info("pass_db_auth(%s): not active");
xerr_info("pass_db_auth(%s): not active", u_name);
goto pass_db_auth_out;
}
crypt_result = crypt(u_pass, pwe->u_hash);
skip_exists:
if (crypt_result) {
if (!strcmp(pwe->u_hash, crypt_result)) {
ret = PASS_DB_AUTH_SUCCESS;
if (pdbctx->debug)
xerr_info("pass_db_auth(%s): pass authentication");
goto pass_db_auth_out;
if ((pdbctx->type == PASS_DB_TYPE_LOCAL) ||
(pdbctx->type == PASS_DB_TYPE_EX_LOCAL)) {
/* authenticate with local crypt() */
crypt_result = crypt(u_pass, pwe->u_hash);
if (crypt_result) {
if (!strcmp(pwe->u_hash, crypt_result)) {
ret = PASS_DB_AUTH_SUCCESS;
if (pdbctx->debug)
xerr_info("pass_db_auth(%s): pass LOCAL authentication", u_name);
goto pass_db_auth_out;
}
}
}
} else if ((pdbctx->type == PASS_DB_TYPE_PAM) ||
(pdbctx->type == PASS_DB_TYPE_EX_PAM)) {
/* authenticate with PAM */
ret = pam_auth(u_name, u_pass, pdbctx->loc);
if (ret == PASS_DB_AUTH_SUCCESS) {
if (pdbctx->debug)
xerr_info("pass_db_auth(%s): pass PAM authentication", u_name);
goto pass_db_auth_out;
}
} /* _PAM */
if (pdbctx->debug)
xerr_info("pass_db_auth(%s): fail authentication");
xerr_info("pass_db_auth(%s): fail authentication", u_name);
pass_db_auth_out:
@ -265,105 +369,124 @@ pass_db_auth_out:
int pass_db_load(struct pass_db_ctx *pdbctx)
{
struct pass_db_entry *pwe;
struct stat cur_sb;
uint16_t u_hash, u_hash_mask;
int au_fd, pw_fd, ret, len, i;
char *pw_buf, *au_buf;
int ret, i;
char *pw_buf, *au_buf, *p_buf;
char *p, *pwdb_u_name, *pwdb_u_hash, *au_name;
uint pw_entry, lineno;
uint pwdb_u_name_len, pwdb_u_hash_len, au_name_len;
int status_default;
int local_status_default, au_only, au_active;
ret = -1;
pw_fd = -1;
au_fd = -1;
pw_buf = (char*)0L;
au_buf = (char*)0L;
au_only = 0; /* authorized users without passwd */
au_active = 0; /* load and process authorized_users */
/* optimization, PASS_DB_TYPE_EX_PAM does not require local resources */
if (pdbctx->type == PASS_DB_TYPE_EX_PAM)
return 0;
/* using authorized_users? */
if ((pdbctx->type == PASS_DB_TYPE_PAM) ||
(pdbctx->type == PASS_DB_TYPE_LOCAL)) {
au_active = 1;
if (!pdbctx->au_fname) {
xerr_warnx("Authorized users file not defined");
goto pass_db_load_out;
}
}
/* username hash mask */
u_hash_mask = (uint16_t)((1<<PASS_DB_HASH_BUCKET_BITS)-1);
/* if no authorized users file then status defaults to active */
if (pdbctx->au_fname)
status_default = PASS_DB_ENTRY_INACTIVE;
else
status_default = PASS_DB_ENTRY_ACTIVE;
/*
* status default is used when the password and authorized_users are
* both active
*/
/* load password database into memory */
/* if using authorized users, then default to inactive */
if (pdbctx->type == PASS_DB_TYPE_LOCAL)
local_status_default = PASS_DB_ENTRY_INACTIVE;
else if (pdbctx->type == PASS_DB_TYPE_EX_LOCAL)
local_status_default = PASS_DB_ENTRY_ACTIVE;
/* open pw database */
if ((pw_fd = open(pdbctx->pw_fname, O_RDONLY, 0)) < 0) {
xerr_warn("open(%s)", pdbctx->pw_fname);
goto pass_db_load_out;
}
/* load metadata */
if (fstat(pw_fd, &pdbctx->pw_sb) < 0) {
xerr_warn("stat(%s)", pdbctx->pw_fname);
goto pass_db_load_out;
}
/*
* special case, PAM + authorized users: do not load passwd database,
* only authorized_users.
*/
if (pdbctx->type == PASS_DB_TYPE_PAM) {
/* allocate storage for pw database */
if (!(pw_buf = malloc(pdbctx->pw_sb.st_size+1))) {
xerr_warn("malloc(%d)", (int)pdbctx->pw_sb.st_size+1);
goto pass_db_load_out;
}
au_only = 1;
if (pdbctx->debug)
xerr_info("pass_db_load(): PAM, loading authorized users only");
/* read in pw database */
if ((len = read(pw_fd, pw_buf, pdbctx->pw_sb.st_size)) < 0) {
xerr_warn("read(%s)", pdbctx->pw_fname);
goto pass_db_load_out;
}
} else {
if (len != pdbctx->pw_sb.st_size) {
xerr_warnx("short read(%s)", pdbctx->pw_fname);
goto pass_db_load_out;
}
/* load authorized_users file if configured into memory */
if (pdbctx->au_fname) {
/* open au database */
if ((au_fd = open(pdbctx->au_fname, O_RDONLY, 0)) < 0) {
xerr_warn("open(%s)", pdbctx->au_fname);
/* load current passwd file metadata */
if (stat(pdbctx->loc, &cur_sb) < 0) {
xerr_warnx("stat(%s)", pdbctx->loc);
goto pass_db_load_out;
}
/* load metadata */
if (fstat(au_fd, &pdbctx->au_sb) < 0) {
xerr_warn("stat(%s)", pdbctx->au_fname);
pdbctx->pw_sb = cur_sb;
/* load password database into memory */
if (!(pw_buf = file_load(pdbctx->loc))) {
xerr_warnx("file_load(%s): failed", pdbctx->loc);
goto pass_db_load_out;
}
/* allocate storage for au database */
if (!(au_buf = malloc(pdbctx->au_sb.st_size+1))) {
xerr_warn("malloc(%d)", (int)pdbctx->au_sb.st_size+1);
goto pass_db_load_out;
}
/* read in au database */
if ((len = read(au_fd, au_buf, pdbctx->au_sb.st_size)) < 0) {
xerr_warn("read(%s)", pdbctx->au_fname);
goto pass_db_load_out;
}
if (len != pdbctx->au_sb.st_size) {
xerr_warnx("short read(%s)", pdbctx->au_fname);
goto pass_db_load_out;
}
} /* pdbctx->au_fname */
/****/
/* count number of lines in the passwd file to predict malloc size */
for (pdbctx->num_entries = 0, p = pw_buf; *p; ++p) {
if (*p == '\n')
++pdbctx->num_entries;
}
/* load authorized_users file if configured */
if (au_active == 1) {
/* load current authorized_users file metadata */
if (stat(pdbctx->au_fname, &cur_sb) < 0) {
xerr_warnx("stat(%s)", pdbctx->au_fname);
goto pass_db_load_out;
}
pdbctx->au_sb = cur_sb;
if (!(au_buf = file_load(pdbctx->au_fname))) {
xerr_warnx("file_load(%s): failed", pdbctx->au_fname);
goto pass_db_load_out;
}
} /* au_active */
if (au_only) {
/* count number of lines in authorized_users to predict malloc size */
for (pdbctx->num_entries = 0, p = au_buf; *p; ++p) {
if (*p == '\n')
++pdbctx->num_entries;
}
} else {
/* count number of lines in passwd file to predict malloc size */
for (pdbctx->num_entries = 0, p = pw_buf; *p; ++p) {
if (*p == '\n')
++pdbctx->num_entries;
}
}
if (pdbctx->debug)
xerr_info("pass_db_load(): loading %d users", pdbctx->num_entries);
if (!(pdbctx->pw_entries = (struct pass_db_entry*)malloc(
pdbctx->num_entries * sizeof (struct pass_db_entry)))) {
xerr_warn("malloc(pw_entries)");
@ -373,8 +496,14 @@ int pass_db_load(struct pass_db_ctx *pdbctx)
bzero(pdbctx->pw_entries,
pdbctx->num_entries * sizeof (struct pass_db_entry));
/* if only using authorized users passwd file parsing is skipped */
if (au_only)
p_buf = au_buf;
else
p_buf = pw_buf;
/* while more lines */
for (p = pw_buf, lineno = 1, pw_entry = 0; *p; ++lineno, ++pw_entry) {
for (p = p_buf, lineno = 1, pw_entry = 0; *p; ++lineno, ++pw_entry) {
/* maf:$1$<hash>::::: */
/* note only u_name:<hash> is required */
@ -389,11 +518,17 @@ int pass_db_load(struct pass_db_ctx *pdbctx)
++p;
break;
}
/* only username if au_only */
if (au_only)
if ((*p == 0) || (*p == '\n'))
break;
/* require minimum of u_name and password field */
if ((*p == 0) || (*p == '\n')) {
*p = 0; /* null terminate */
xerr_warnx("pass_db_auth(%s): lineno=%d, parse error at %s",
pdbctx->pw_fname, lineno, pwdb_u_name);
pdbctx->loc, lineno, pwdb_u_name);
ret = PASS_DB_AUTH_ERROR;
goto pass_db_load_out;
}
@ -402,18 +537,23 @@ int pass_db_load(struct pass_db_ctx *pdbctx)
} /* extract u_name */
/* hash of u_pass is next */
pwdb_u_hash = p;
/* password hash is next if not au_only */
if (!au_only) {
for (pwdb_u_hash_len = 0;;pwdb_u_hash_len++) {
/* hash of u_pass is next */
pwdb_u_hash = p;
/* end of u_pass hash field (possibly EOL or EOF */
if ((*p == 0) || (*p == '\n') || (*p == ':'))
break;
for (pwdb_u_hash_len = 0;;pwdb_u_hash_len++) {
++p;
/* end of u_pass hash field (possibly EOL or EOF */
if ((*p == 0) || (*p == '\n') || (*p == ':'))
break;
} /* extract u_pass hash */
++p;
} /* extract u_pass hash */
}
/* skip to next line */
for (; *p && *p != '\n'; ++p);
@ -424,31 +564,37 @@ int pass_db_load(struct pass_db_ctx *pdbctx)
/* u_name len 0 is illegal */
if (pwdb_u_name_len == 0) {
xerr_warnx("pass_db_auth(%s): lineno=%d, pwdb_u_name_len=0",
pdbctx->pw_fname, lineno);
pdbctx->loc, lineno);
ret = PASS_DB_AUTH_ERROR;
goto pass_db_load_out;
}
/* user_hash len 0 is illegel */
if (pwdb_u_hash_len == 0) {
xerr_warnx("pass_db_auth(%s): lineno=%d, pwdb_u_hash_len=0",
pdbctx->pw_fname, lineno);
ret = PASS_DB_AUTH_ERROR;
goto pass_db_load_out;
/* u_hash only if parsing passwd */
if (!au_only) {
/* u_hash len 0 is illegel */
if (pwdb_u_hash_len == 0) {
xerr_warnx("pass_db_auth(%s): lineno=%d, pwdb_u_hash_len=0",
pdbctx->loc, lineno);
ret = PASS_DB_AUTH_ERROR;
goto pass_db_load_out;
}
/* bounds check u_hash_len */
if (pwdb_u_hash_len > PASS_DB_USER_HASH_LEN) {
xerr_warnx("pass_db_auth(%s): lineno=%d, pwdb_u_hash_len=%d >%d ",
pdbctx->loc, lineno, pwdb_u_hash_len, PASS_DB_USER_HASH_LEN);
ret = PASS_DB_AUTH_ERROR;
goto pass_db_load_out;
}
}
/* bounds check pwdb length */
if (pwdb_u_hash_len > PASS_DB_USER_HASH_LEN) {
xerr_warnx("pass_db_auth(%s): lineno=%d, pwdb_u_hash_len=%d >%d ",
pdbctx->pw_fname, lineno, pwdb_u_hash_len, PASS_DB_USER_HASH_LEN);
ret = PASS_DB_AUTH_ERROR;
goto pass_db_load_out;
}
/* bounds check pwdb len */
/* bounds check u_name_len */
if (pwdb_u_name_len > PASS_DB_USER_NAME_LEN) {
xerr_warnx("pass_db_auth(%s): lineno=%d, pwdb_u_name=%d >%d ",
pdbctx->pw_fname, lineno, pwdb_u_name_len, PASS_DB_USER_NAME_LEN);
pdbctx->loc, lineno, pwdb_u_name_len, PASS_DB_USER_NAME_LEN);
ret = PASS_DB_AUTH_ERROR;
goto pass_db_load_out;
}
@ -457,11 +603,17 @@ int pass_db_load(struct pass_db_ctx *pdbctx)
/* store as C string (null termination is handled above in bzero() ) */
bcopy(pwdb_u_name, &pwe->u_name, pwdb_u_name_len);
bcopy(pwdb_u_hash, &pwe->u_hash, pwdb_u_hash_len);
pwe->status = status_default;
pwe->u_name_len = pwdb_u_name_len;
pwe->u_hash_len = pwdb_u_hash_len;
if (!au_only) {
bcopy(pwdb_u_hash, &pwe->u_hash, pwdb_u_hash_len);
pwe->u_hash_len = pwdb_u_hash_len;
pwe->status = local_status_default;
} else {
pwe->u_hash_len = 0;
pwe->status = PASS_DB_ENTRY_ACTIVE;
}
/* populate hash lookup table */
u_hash = 0;
for (i = 0; i < pwdb_u_name_len; ++i) {
@ -484,7 +636,7 @@ int pass_db_load(struct pass_db_ctx *pdbctx)
* if using authorized_users mark pdbctx entries with an active
* user as active
*/
if (pdbctx->au_fname) {
if (au_active && (!au_only)) {
/* while more lines */
for (p = au_buf, lineno = 1; *p; ++lineno) {
@ -525,7 +677,7 @@ int pass_db_load(struct pass_db_ctx *pdbctx)
} /* more lines */
} /* au_fname */
} /* au_active && !au_only */
pdbctx->state = PASS_DB_STATE_LOADED;
@ -533,12 +685,6 @@ int pass_db_load(struct pass_db_ctx *pdbctx)
pass_db_load_out:
if (pw_fd != -1)
close (pw_fd);
if (au_fd != -1)
close (au_fd);
if (pw_buf)
free(pw_buf);
@ -644,3 +790,124 @@ void pass_db_stats(struct pass_db_ctx *pdbctx)
} /* hash_bucket */
} /* pass_db_stat() */
static int pam_auth(char *user_name, char *user_pass, char *svc_name)
{
struct pam_conv pam_conv;
pam_handle_t *pam_h;
int pam_err, pass_db_ret;
bzero(&pam_conv, sizeof pam_conv);
pam_h = (pam_handle_t*)0L;
pam_conv.conv = &pam_mem_conv;
pam_conv.appdata_ptr = (void*)0L;
pass_db_ret = PASS_DB_AUTH_ERROR;
global_user_pass = user_pass;
/* PAM must run as root */
if (getuid() != 0) {
xerr_warnx("pam_db_auth(): getuid() != 0");
goto pam_auth_out;
}
/* startup PAM */
if ((pam_err = pam_start (svc_name, user_name, &pam_conv,
&pam_h)) != PAM_SUCCESS) {
xerr_warnx("pam_start(): %s", pam_strerror(pam_h, pam_err));
goto pam_auth_out;
}
pam_err = pam_authenticate(pam_h, 0);
if (pam_err == PAM_SUCCESS) {
pass_db_ret = PASS_DB_AUTH_SUCCESS;
} else {
pass_db_ret = PASS_DB_AUTH_FAIL;
}
pam_auth_out:
/* shutdown PAM */
if (pam_h)
pam_end(pam_h, 0);
return pass_db_ret;
} /* pam_db_auth */
int pam_mem_conv (int pam_nmsg, const struct pam_message **pam_msgh,
struct pam_response **pam_resph, void *pam_app_data)
{
int i, pam_err, pass_len;
*pam_resph = (void*)0L;
pass_len = strlen(global_user_pass);
if ((pam_nmsg <= 0) || (pam_nmsg >= PAM_MAX_NUM_MSG)) {
xerr_warnx("check_conv(): invalid pam_nmsg=%d", pam_nmsg);
pam_err = PAM_CONV_ERR;
goto pam_mem_conv_out;
}
/* allocate storage for responses, to be free()'d by caller or us on err */
if (!(*pam_resph = (struct pam_response*)malloc(pam_nmsg *
sizeof (struct pam_response) ))) {
xerr_warn("malloc(pam_nmsg=%d)", pam_nmsg);
pam_err = PAM_BUF_ERR;
goto pam_mem_conv_out;
}
bzero(*pam_resph, pam_nmsg*sizeof (struct pam_response));
for (i = 0; i < pam_nmsg; ++i) {
switch (pam_msgh[i]->msg_style) {
case PAM_PROMPT_ECHO_OFF:
case PAM_PROMPT_ECHO_ON:
/* allocate space for password */
if (!((*pam_resph)[i].resp = (char*)malloc(pass_len+1))) {
xerr_warn("malloc(l_passwd):");
pam_err = PAM_BUF_ERR;
goto pam_mem_conv_out;
}
bcopy(global_user_pass, (*pam_resph)[i].resp, pass_len+1);
break;
case PAM_ERROR_MSG:
case PAM_TEXT_INFO:
xerr_warnx("PAM_MSG: %s", pam_msgh[i]->msg);
break;
default:
xerr_warnx("Ignoring unexpected msg_style=%d", pam_msgh[i]->msg_style);
break;
} /* switch */
} /* foreach message */
return (PAM_SUCCESS);
pam_mem_conv_out:
if (*pam_resph) {
for (i = 0; i < pam_nmsg; ++i)
if ((*pam_resph)[i].resp)
free((*pam_resph)[i].resp);
free(*pam_resph);
}
return pam_err;
} /* pam_mem_conv */

View file

@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: pw.h 13 2009-11-26 16:37:03Z maf $
* $Id: pw.h 155 2011-04-06 02:25:43Z maf $
*/
@ -40,6 +40,10 @@
#define PASS_DB_ENTRY_INACTIVE 0
#define PASS_DB_ENTRY_ACTIVE 1
#define PASS_DB_TYPE_LOCAL 1
#define PASS_DB_TYPE_EX_LOCAL 2 /* ignore authorized_users */
#define PASS_DB_TYPE_PAM 3
#define PASS_DB_TYPE_EX_PAM 4 /* ignore authorized_users */
#define PASS_DB_AUTH_SUCCESS 0
#define PASS_DB_AUTH_FAIL 1
@ -54,8 +58,9 @@ struct pass_db_ctx {
struct stat pw_sb;
struct stat au_sb;
int state;
char *pw_fname;
char *au_fname;
int type;
char *loc; /* password filename or PAM service name */
char *au_fname; /* authorized users filename */
uint num_entries;
struct pass_db_entry *pw_entries;
SLIST_HEAD(pass_db_head, pass_db_entry) bucket[1<<PASS_DB_HASH_BUCKET_BITS];
@ -71,7 +76,7 @@ struct pass_db_entry {
char u_hash[PASS_DB_USER_HASH_LEN+1];
};
struct pass_db_ctx *pass_db_ctx_new(char *pw_fname, char *au_fname);
struct pass_db_ctx *pass_db_ctx_new(char *loc, char *au_fname, int type);
void pass_db_ctx_free(struct pass_db_ctx *pdbctx);
int pass_db_auth(struct pass_db_ctx *pdbctx, char *user_name, char *user_pass);
int pass_db_load(struct pass_db_ctx *pdbctx);

103
urd/rad.c
View file

@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: rad.c 13 2009-11-26 16:37:03Z maf $
* $Id: rad.c 157 2011-04-06 03:57:29Z maf $
*/
#include <sys/types.h>
@ -194,6 +194,7 @@ int urd_req_decode(struct urd_ctx *urdctx)
urdctx->req.tlv_NAS_Identifier = (struct urd_tlv*)0L;
urdctx->req.tlv_User_Password = (struct urd_tlv*)0L;
urdctx->req.tlv_State = (struct urd_tlv*)0L;
bzero(&urdctx->req.user_name_base, URD_USER_NAME_LEN+1);
bzero(&urdctx->req.user_name, URD_USER_NAME_LEN+1);
bzero(&urdctx->req.user_pass, URD_USER_PASS_LEN+1);
urdctx->req.state_counter = 0;
@ -301,6 +302,19 @@ int urd_req_decode(struct urd_ctx *urdctx)
urdctx->req.tlv_User_Name->len);
urdctx->req.user_name[urdctx->req.tlv_User_Name->len] = 0;
/*
* hack to allow multiple usernames to authenticate off the same
* base name. Allows a single user to sign on to device more than
* once when the device only supports single user sessions.
*/
bcopy(urdctx->req.tlv_User_Name->val, &urdctx->req.user_name_base,
urdctx->req.tlv_User_Name->len);
urdctx->req.user_name_base[urdctx->req.tlv_User_Name->len] = 0;
for (i = 0; i < urdctx->req.tlv_User_Name->len; ++i)
if (urdctx->req.user_name_base[i] == '#')
urdctx->req.user_name_base[i] = 0;
} /* urdctx->req.tlv_User_Name */
/* C string */
@ -405,13 +419,13 @@ void urd_req_dump(struct urd_ctx *urdctx)
int buf_l, i, j, decode_type;
char buf[1024];
buf_l = snprintf(buf, 1024,
buf_l = snprintf(buf, sizeof(buf),
"pkt.code=%2.2X, pkt.id=%2.2X, pkt.len=%2.2X, pkt.auth=",
(int)urdctx->req.dgram_header.code,
(int)urdctx->req.dgram_header.identifier,
(int)urdctx->req.dgram_header.length);
for (j = 0; j < RADIUS_AUTHENTICATOR_LEN; ++j)
buf_l += snprintf(buf+buf_l, 1024-buf_l, "%2.2X",
buf_l += snprintf(buf+buf_l, sizeof(buf)-buf_l, "%2.2X",
((int)urdctx->req.dgram_header.authenticator[j]));
xerr_info(buf);
@ -428,6 +442,10 @@ void urd_req_dump(struct urd_ctx *urdctx)
decode_type = URD_DECODE_TYPE_CHAR;
break;
case RADIUS_ATTRIB_USER_PASSWORD:
decode_type = URD_DECODE_TYPE_HIDDEN;
break;
case RADIUS_ATTRIB_NAS_IP_ADDRESS:
case RADIUS_ATTRIB_FRAMED_IP_ADDRESS:
case RADIUS_ATTRIB_FRAMED_IP_NETMASK:
@ -440,32 +458,36 @@ void urd_req_dump(struct urd_ctx *urdctx)
} /* switch */
buf_l = snprintf(buf, 1024,
buf_l = snprintf(buf, sizeof(buf),
" TLV type=%d, len=%d, val=", (int)urdctx->req.tlv[i].type,
(int)urdctx->req.tlv[i].len);
switch (decode_type) {
case URD_DECODE_TYPE_HEX:
buf_l += snprintf(buf+buf_l, 1024-buf_l, "H ");
buf_l += snprintf(buf+buf_l, sizeof(buf)-buf_l, "H ");
for (j = 0; j < urdctx->req.tlv[i].len; ++j)
buf_l += snprintf(buf+buf_l, 1024-buf_l, "%2.2X",
buf_l += snprintf(buf+buf_l, sizeof(buf)-buf_l, "%2.2X",
(int)urdctx->req.tlv[i].val[j]);
break;
case URD_DECODE_TYPE_CHAR:
buf_l += snprintf(buf+buf_l, 1024-buf_l, "C ");
buf_l += snprintf(buf+buf_l, sizeof(buf)-buf_l, "C ");
for (j = 0; j < urdctx->req.tlv[i].len; ++j)
buf_l += snprintf(buf+buf_l, 1024-buf_l, "%c",
buf_l += snprintf(buf+buf_l, sizeof(buf)-buf_l, "%c",
urdctx->req.tlv[i].val[j]);
break;
case URD_DECODE_TYPE_IP:
buf_l += snprintf(buf+buf_l, 1024-buf_l, "I %d.%d.%d.%d",
buf_l += snprintf(buf+buf_l, sizeof(buf)-buf_l, "I %d.%d.%d.%d",
(int)urdctx->req.tlv[i].val[0], (int)urdctx->req.tlv[i].val[1],
(int)urdctx->req.tlv[i].val[2], (int)urdctx->req.tlv[i].val[3]);
break;
case URD_DECODE_TYPE_HIDDEN:
buf_l += snprintf(buf+buf_l, sizeof(buf)-buf_l, "X <hidden>");
break;
} /* switch */
xerr_info(buf);
@ -498,15 +520,15 @@ void urd_req_dump(struct urd_ctx *urdctx)
*
*/
int urd_rep_encode(struct urd_ctx *urdctx, uint8_t code,
uint64_t state_counter, int rep_encode_flags)
uint64_t state_counter, uint64_t otp_count, int rep_encode_flags)
{
struct radius_dgram_header dgram_header, *dh;
struct urd_tlv_state tlv_state;
struct urd_tlv_rep_msg tlv_rep_msg;
u_char md_val[EVP_MAX_MD_SIZE];
u_char md_val[EVP_MAX_MD_SIZE], *c;
char fmt_buf[64];
uint md_len;
int i, pkt_p;
char *c;
bzero(&dgram_header, sizeof dgram_header);
bzero(&tlv_state, sizeof tlv_state);
@ -534,7 +556,7 @@ int urd_rep_encode(struct urd_ctx *urdctx, uint8_t code,
tlv_state.val[0] = 'u'; tlv_state.val[1] = 'r';
tlv_state.val[2] = 'd'; tlv_state.val[3] = ':';
c = (char*)&state_counter;
c = (u_char*)&state_counter;
i = 19;
while (i > 4) {
@ -550,14 +572,27 @@ int urd_rep_encode(struct urd_ctx *urdctx, uint8_t code,
/* add reply message? */
if (rep_encode_flags & URD_ENCODE_FLAG_MSG) {
dgram_header.length += sizeof (tlv_rep_msg);
i = snprintf(fmt_buf, sizeof(fmt_buf), "%" PRIu64, otp_count);
/* should never happen */
if (i > URD_TLV_REPLY_MSG_LEN) {
xerr_warnx("reply msg encode failed, i=%d", i);
i = URD_TLV_REPLY_MSG_LEN;
}
/*
* calculate size of tlv_rep_msg. The full URD_TLV_REPLY_MSG_LEN
* space ay not be used and is truncated. type(1) + len(1) + message(i)
*/
tlv_rep_msg.len = 1 + 1 + i;
/* add len to total encoded size */
dgram_header.length += tlv_rep_msg.len;
/* XXX hard coded to ABCD... */
tlv_rep_msg.type = RADIUS_ATTRIB_REPLY_MESSAGE;
tlv_rep_msg.len = sizeof (tlv_rep_msg);
for (i = 0; i < 7; ++i)
tlv_rep_msg.val[i] = 'A'+i;
tlv_rep_msg.val[7] = 0;
/* copy in otp_count in ASCII */
bcopy(&fmt_buf, &tlv_rep_msg.val, i);
} /* URD_ENCODE_FLAG_MSG */
@ -582,9 +617,8 @@ int urd_rep_encode(struct urd_ctx *urdctx, uint8_t code,
}
if (rep_encode_flags & URD_ENCODE_FLAG_MSG) {
bcopy(&tlv_rep_msg, (char*)&urdctx->rep.pkt_buf + pkt_p,
sizeof(tlv_rep_msg));
pkt_p += sizeof(tlv_rep_msg);
bcopy(&tlv_rep_msg, (char*)&urdctx->rep.pkt_buf + pkt_p, tlv_rep_msg.len);
pkt_p += tlv_rep_msg.len;
}
/* MD5(reply packet + secret) */
@ -672,7 +706,7 @@ void urd_ctx_free(struct urd_ctx *urdctx)
*
*/
int urd_req_cache_update(struct urd_ctx *urdctx, uint8_t rep_code,
uint64_t state_counter, int req_cache_flags)
uint64_t state_counter, uint64_t otp_count, int req_cache_flags)
{
uint16_t req_hash, req_hash_mask, state_hash, state_hash_mask;
struct urd_req_cache_entry *e;
@ -710,7 +744,7 @@ int urd_req_cache_update(struct urd_ctx *urdctx, uint8_t rep_code,
/* insert entry into hash bucket state_chain */
LIST_INSERT_HEAD(&urdctx->state_cache_bucket[state_hash], e, state_chain);
e->flags = URD_STATE_CACHE_FLAGS_INUSE;
e->flags = URD_STATE_CACHE_FLAG_INUSE;
} /* hash table for state */
@ -729,11 +763,13 @@ int urd_req_cache_update(struct urd_ctx *urdctx, uint8_t rep_code,
e->rad_code = rep_code;
e->otp_count = otp_count;
e->rad_id = urdctx->req.dgram_header.identifier;
e->rexmit_count = 0;
e->flags ^= URD_REQ_CACHE_FLAGS_INUSE;
e->flags ^= URD_REQ_CACHE_FLAG_INUSE;
/* rollover */
if (urdctx->req_cache_len == URD_REQ_CACHE_ENTRIES)
@ -741,23 +777,23 @@ int urd_req_cache_update(struct urd_ctx *urdctx, uint8_t rep_code,
/* if the current entry was previously in use, remove from hash chain */
if (urdctx->req_cache[urdctx->req_cache_len].flags &
URD_REQ_CACHE_FLAGS_INUSE) {
URD_REQ_CACHE_FLAG_INUSE) {
LIST_REMOVE(&urdctx->req_cache[urdctx->req_cache_len], req_chain);
urdctx->req_cache[urdctx->req_cache_len].flags &=\
~URD_REQ_CACHE_FLAGS_INUSE;
~URD_REQ_CACHE_FLAG_INUSE;
} /* in use? */
/* if the current entry was previously in use, remove from hash chain */
if (urdctx->req_cache[urdctx->req_cache_len].flags &
URD_STATE_CACHE_FLAGS_INUSE) {
URD_STATE_CACHE_FLAG_INUSE) {
LIST_REMOVE(&urdctx->req_cache[urdctx->req_cache_len], state_chain);
urdctx->req_cache[urdctx->req_cache_len].flags &=\
~URD_STATE_CACHE_FLAGS_INUSE;
~URD_STATE_CACHE_FLAG_INUSE;
} /* in use? */
@ -774,6 +810,9 @@ int urd_req_cache_update(struct urd_ctx *urdctx, uint8_t rep_code,
* UserName and UserPassWord TLV's must be in request (req)
* and be of length <= URD_USER_NAME_LEN/URD_USER_PASS_LEN
*
* code, otp_count, and state_counter will be updated on cache hit,
* else they are unchanged.
*
* Lookup request in cache by Authenticator field. Additionally
* verify identifier, user_name, user_pass and state (if present) match
* the cache'd request. If the entry has not expired (older than
@ -785,7 +824,7 @@ int urd_req_cache_update(struct urd_ctx *urdctx, uint8_t rep_code,
*
*/
int urd_req_cache_lookup(struct urd_ctx *urdctx, uint8_t *code,
uint64_t *state_counter)
uint64_t *state_counter, uint64_t *otp_count, int *cache_flags)
{
time_t now;
uint16_t hash, hash_mask;
@ -843,6 +882,8 @@ int urd_req_cache_lookup(struct urd_ctx *urdctx, uint8_t *code,
/* cached result code and state */
*code = e->rad_code;
*state_counter = e->state_counter;
*otp_count = e->otp_count;
*cache_flags = e->flags;
match = 1;
break;
@ -885,6 +926,8 @@ int urd_req_cache_lookup(struct urd_ctx *urdctx, uint8_t *code,
* UserName and UserPassWord TLV's must be in request (req)
* and be of length <= URD_USER_NAME_LEN/URD_USER_PASS_LEN
*
* code will be updated on cache hit, else it is left unchanged.
*
* Lookup request in cache by state field. Additionally
* verify user_name matches the initial Access-Request.
* If the entry has not expired (older than URD_STATE_CACHE_LIFETIME seconds

View file

@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: rad.h 13 2009-11-26 16:37:03Z maf $
* $Id: rad.h 157 2011-04-06 03:57:29Z maf $
*/
#include <openssl/evp.h>
@ -42,8 +42,9 @@
#define URD_PACKET_LEN_MIN 20 /* minimum datagram length */
#define URD_TLV_STATE_LEN 20 /* length of state tlv data */
/* XXX */
#define URD_TLV_REPLY_MSG_LEN 8 /* length of state reply message data */
/* can encode a PRIu64 which is up to 20 digits in ASCII */
#define URD_TLV_REPLY_MSG_LEN 20 /* length of state reply message data */
/*
* The cache length should be a minimum (max queries/second * cache seconds)
@ -64,8 +65,8 @@
#define URD_REQ_CACHE_HIT 1 /* cache hit */
#define URD_REQ_CACHE_MISS 0 /* cache miss */
#define URD_REQ_CACHE_FLAGS_INUSE 0x1 /* cache entry is in use */
#define URD_STATE_CACHE_FLAGS_INUSE 0x2 /* cache entry is in use */
#define URD_REQ_CACHE_FLAG_INUSE 0x1 /* cache entry is in use */
#define URD_STATE_CACHE_FLAG_INUSE 0x2 /* cache entry is in use */
/* Hash buckets is dependent on the hash function.. */
#define URD_REQ_HASH_BUCKET_BITS 16 /* number of hash buckets */
@ -76,6 +77,7 @@
#define URD_STATE_CACHE_MISS 0 /* cache miss */
#define URD_CACHE_FLAG_STATE 0x1 /* prep lookup by state too */
#define URD_CACHE_FLAG_MSG 0x2 /* hint to encode message */
#define URD_ENCODE_FLAG_STATE 0x1 /* encode state in reply */
#define URD_ENCODE_FLAG_MSG 0x2 /* encode message in reply */
@ -139,6 +141,7 @@
#define URD_DECODE_TYPE_HEX 0
#define URD_DECODE_TYPE_CHAR 1
#define URD_DECODE_TYPE_IP 2
#define URD_DECODE_TYPE_HIDDEN 3
struct radius_dgram_header {
uint8_t code;
@ -170,6 +173,7 @@ struct urd_req_cache_entry {
char user_name[URD_USER_NAME_LEN+1]; /* key */
char user_pass[URD_USER_PASS_LEN+1]; /* key */
uint64_t state_counter; /* state_hash/key */
uint64_t otp_count; /* OTP count */
time_t create_time; /* cache maintenance */
uint8_t rad_code; /* data to be cached */
uint8_t rad_id; /* req_hash/key */
@ -187,7 +191,7 @@ struct urd_req_cache_entry {
* rce_index = 0;
*
* when storing an entry (rce_index always points to the next free entry)
* if (entry.flags & URD_REQ_CACHE_FLAGS_INUSE) then
* if (entry.flags & URD_REQ_CACHE_FLAG_INUSE) then
* remove entry from req_chain before using.
*
* counter initialized to 1, counter=0 is a stateless cache entry, ie
@ -203,16 +207,17 @@ struct urd_req_cache_entry {
*/
struct urd_req {
EVP_MD_CTX mdctx; /* MD5 context */
uint8_t pkt_buf[URD_MAX_DGRAM_LEN]; /* raw datagram */
struct radius_dgram_header dgram_header; /* datagram header */
struct sockaddr_in rem_addr; /* remote host */
int pkt_len; /* packet length */
int tlv_count; /* number TLV's */
struct urd_tlv tlv[URD_MAX_TLV]; /* decoded TLV's */
char user_name[URD_USER_NAME_LEN+1]; /* C string */
char user_pass[URD_USER_PASS_LEN+1]; /* C string (clear) */
uint64_t state_counter; /* decoded state TLV */
EVP_MD_CTX mdctx; /* MD5 context */
uint8_t pkt_buf[URD_MAX_DGRAM_LEN]; /* raw datagram */
struct radius_dgram_header dgram_header; /* datagram header */
struct sockaddr_in rem_addr; /* remote host */
int pkt_len; /* packet length */
int tlv_count; /* number TLV's */
struct urd_tlv tlv[URD_MAX_TLV]; /* decoded TLV's */
char user_name[URD_USER_NAME_LEN+1]; /* C string */
char user_pass[URD_USER_PASS_LEN+1]; /* C string (clear) */
char user_name_base[URD_USER_NAME_LEN+1]; /* C string (clear) */
uint64_t state_counter; /* decoded state TLV */
/* shortcuts */
struct urd_tlv *tlv_User_Name;
struct urd_tlv *tlv_NAS_IP_Address;
@ -246,13 +251,13 @@ struct urd_ctx {
int urd_req_decode(struct urd_ctx *urdctx);
void urd_req_dump(struct urd_ctx *urdctx);
int urd_rep_encode(struct urd_ctx *urdctx, uint8_t code,
uint64_t state_counter, int rep_encode_flags);
uint64_t state_counter, uint64_t otp_count, int rep_encode_flags);
struct urd_ctx *urd_ctx_new(char *rsecret);
void urd_ctx_free(struct urd_ctx *urdctx);
int urd_req_cache_update(struct urd_ctx *urdctx, uint8_t code,
uint64_t state_counter, int req_cache_flags);
uint64_t state_counter, uint64_t otp_count, int req_cache_flags);
int urd_req_cache_lookup(struct urd_ctx *urdctx, uint8_t *code,
uint64_t *state_counter);
uint64_t *state_counter, uint64_t *otp_count, int *cache_flags);
int urd_state_cache_lookup(struct urd_ctx *urdctx, uint8_t *code);
void urd_state_cache_stats(struct urd_ctx *urdctx);
void urd_req_cache_stats(struct urd_ctx *urdctx);

239
urd/rc.d/urd Normal file
View file

@ -0,0 +1,239 @@
#!/bin/sh
# PROVIDE: urd
# REQUIRE: DAEMON
. /etc/rc.subr
# urd_enable="YES"
# urd_list="engvpn1 testvpn1"
# urd_engvpn1_dir="/var/urd/engvpn1"
# urd_engvpn1_ip="10.1.0.1"
# urd_engvpn1_flags="-dD"
# urd_engvpn1_passwd="passwd"
# urd_engvpn1_authorized_users="authorized_users"
# urd_engvpn1_otp="otp.db"
# urd_engvpn1_secret="server_secret"
# urd_engvpn1_pid="pid.10.1.0.1"
# urd_engvpn1_pgm="/usr/local/ootp/bin/urd"
# urd_engvpn1_service="urd"
name="urd"
rcvar=`set_rcvar`
start_cmd="urd_start"
stop_cmd="urd_stop"
status_cmd="urd_status"
extra_commands="status list"
extra_arg=$2
list_cmd="urd_list"
w="/usr/local/ootp/bin"
RTPRIO="/usr/sbin/rtprio"
ARGV0="/usr/local/bin/argv0"
URD="$w/urd"
if [ -z "$autoboot" ]; then
autoboot="NO"
fi
# shutdown does a fast stop, use to trigger stop all
if echo $1 | egrep '^fast'>/dev/null; then
DO_ALL=1
else
DO_ALL=0
fi
# startup scripts set autoboot, start all instances
if checkyesno autoboot; then
DO_ALL=1
fi
load_rc_config $name
urd_debug()
{
echo "********"
echo "urd_instance=$n"
echo "dir=$urd_dir"
echo "ip=$urd_ip"
echo "port=$urd_port"
echo "flags=$urd_flags"
echo "passwd=$urd_passwd"
echo "authorized_users=$urd_au"
echo "otpdb=$urd_otpdb"
echo "server_secret=$urd_ss"
echo "pid=$urd_pid"
echo "pgm=$urd_pgm"
}
urd_expand()
{
eval urd_dir=\$urd_${1}_dir
eval urd_ip=\$urd_${1}_ip
eval urd_port=\$urd_${1}_port
eval urd_flags=\$urd_${1}_flags
eval urd_passwd=\$urd_${1}_passwd
eval urd_au=\$urd_${1}_authorized_users
eval urd_otpdb=\$urd_${1}_otpdb
eval urd_ss=\$urd_${1}_server_secret
eval urd_pid=\$urd_${1}_pid
eval urd_pgm=\$urd_${1}_pgm
eval urd_service=\$urd_${1}_service
if [ -z "$urd_dir" ]; then
urd_dir="/var/urd/$1"
fi
if [ -z "$urd_ip" ]; then
urd_ip="0.0.0.0"
fi
if [ -z "$urd_port" ]; then
urd_port="1812"
fi
if [ -z "$urd_passwd" ]; then
urd_passwd="$urd_dir/passwd"
fi
if [ -z "$urd_au" ]; then
urd_au="$urd_dir/authorized_users"
fi
if [ -z "$urd_otpdb" ]; then
urd_otpdb="$urd_dir/otpdb"
fi
if [ -z "$urd_pid" ]; then
if [ "X$urd_ip" = "X0.0.0.0" ]; then
urd_pid="$urd_dir/pid"
else
urd_pid="$urd_dir/pid.$urd_ip"
fi
fi
if [ -z "$urd_ss" ]; then
urd_ss="$urd_dir/server_secret"
fi
if [ -z "$urd_pgm" ]; then
urd_pgm=$URD
fi
if [ -z "$urd_service" ]; then
urd_service="urd"
fi
} # urd_expand
urd_status()
{
if [ ! -z "$extra_arg" ]; then
urd_list=$extra_arg
fi
for n in $urd_list; do
echo -n "$n "
a0="urd.$n"
p=`check_process $a0`
if [ -z "$p" ]; then
echo "*** not running ***"
else
echo $p
fi
done
} # urd_status
urd_list()
{
for n in $urd_list; do
urd_expand $n
urd_debug $n
done
} # urd_list
urd_start()
{
if [ "$DO_ALL" -eq 0 ]; then
if [ -z "$extra_arg" ]; then
err 1 "start requires config name argument. Try list."
fi
urd_list=$extra_arg
fi
PATH=$w:$PATH
for n in $urd_list; do
urd_expand $n
if [ ! -d "$urd_dir" ]; then
err 1 "$n: missing config dir $urd_dir"
fi
a0="urd.$n"
echo starting urd for $n.
# pre 173 does not take -V
if [ "$urd_service" = "urd" ]; then
$ARGV0 $urd_pgm $a0 -a $urd_au -b $urd_ip -B $urd_port\
-o $urd_otpdb -p $urd_passwd -P $urd_pid -s $urd_ss \
$urd_flags
else
$ARGV0 $urd_pgm $a0 -a $urd_au -b $urd_ip -B $urd_port\
-o $urd_otpdb -p $urd_passwd -P $urd_pid -s $urd_ss \
-V $urd_service $urd_flags
fi
done
} # urd_start
urd_stop()
{
if [ "$DO_ALL" -eq 0 ]; then
if [ -z "$extra_arg" ]; then
err 1 "stop requires config name argument. Try list."
fi
urd_list=$extra_arg
fi
for n in $urd_list; do
urd_expand $n
if [ ! -d "$urd_dir" ]; then
err 1 "$n: missing config dir $urd_dir"
fi
a0="urd.$n"
pid=`check_process $a0`
if [ -n "$pid" ]; then
kill -9 $pid
echo "$n: stopped"
else
echo "$n: not running."
fi
done
} # urd_stop
run_rc_command "$1"

286
urd/urd.c
View file

@ -24,7 +24,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: urd.c 50 2009-12-15 01:37:19Z maf $
* $Id: urd.c 176 2011-05-16 02:17:30Z maf $
*/
#include <sys/types.h>
@ -34,6 +34,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <getopt.h>
#include <netdb.h>
#include <errno.h>
#include <inttypes.h>
@ -56,7 +57,6 @@
/*
* XXX
* urd_rep_msg in access-challenge hard coded to ABC..
* copy proxy variables into reply packet per RFC?
* packet stress testing
*/
@ -66,9 +66,12 @@ static int server_secret_load(char *fname, char *buf, int buf_len);
static u_long scan_ip(char *s);
static int write_pidfile(char *fname);
#define URDCTX_USER_NAME (allow_n_logins ?\
urdctx->req.user_name_base : urdctx->req.user_name)
int main(int argc, char **argv)
{
extern char *ootp_version;
struct sockaddr_in loc_addr;
struct urd_ctx *urdctx;
struct pass_db_ctx *pdbctx;
@ -76,26 +79,65 @@ int main(int argc, char **argv)
struct otp_ctx *otpctx;
struct otp_user ou;
char *otpdb_fname;
int otp_skip_unknown, otpdb_flags, otp_enable;
int otp_allow_unknown, otpdb_flags, otp_enable;
#endif /* OOTP_ENABLE */
fd_set rfd;
u_long tmpul;
uint64_t rep_state;
uint64_t rep_state, rep_otp_count;
uint32_t local_ip;
uint16_t local_port;
uint8_t rep_code;
uint rem_addr_len;
char *authorized_users_fname, *pwfile_fname, *server_secret_fname, *endptr;
char server_secret[URD_SECRET_LEN+1], buf[1024], *pid_fname;
int rep_enc_flags, rep_cache_flags, debug, daemon_mode;
char *au_fname, *pwfile_fname, *server_secret_fname, *endptr, *loc;
char server_secret[URD_SECRET_LEN+1], buf[1024], *pid_fname, *as_name;
char *service;
int rep_enc_flags, rep_cache_flags, debug, daemon_mode, pdb_type;
int drop, drop_mode, req_cache_hit, buf_l, pkt_fd, r, i, otp_window;
int opt_version, otp_display_count, tmp_cache_flags;
int disable_authorized_users, allow_n_logins;
struct option longopts[] = {
{ "authorized-users-db", 1, (void*)0L, 'a'},
{ "disable-authorized-users", 0, (void*)0L, 'A'},
{ "bind-ip-address", 1, (void*)0L, 'b'},
{ "bind-udp-port", 1, (void*)0L, 'B'},
#ifdef OOTP_ENABLE
{ "display-count", 0, (void*)0L, 'c'},
#endif /* OOTP_ENABLE */
{ "debug", 1, (void*)0L, 'd'},
{ "disable-daemon-mode", 0, (void*)0L, 'D'},
{ "help", 0, (void*)0L, 'h'},
{ "help", 0, (void*)0L, '?'},
{ "pam-authentication-enable", 0, (void*)0L, 'm'},
{ "pam-authentication-exclusive", 0, (void*)0L, 'M'},
{ "n-logins-enable", 0, (void*)0L, 'n'},
#ifdef OOTP_ENABLE
{ "otp-db", 1, (void*)0L, 'o'},
{ "otp-disable", 0, (void*)0L, 'O'},
#endif /* OOTP_ENABLE */
{ "password-db", 1, (void*)0L, 'p'},
{ "pidfile", 1, (void*)0L, 'P'},
{ "server-secret", 1, (void*)0L, 's'},
{ "pam-service-name", 1, (void*)0L, 'S'},
#ifdef OOTP_ENABLE
{ "otp-allow-unknown-user", 0, (void*)0L, 'u'},
{ "service-name", 0, (void*)0L, 'V'},
{ "otp-challenge-window", 1, (void*)0L, 'w'},
#endif /* OOTP_ENABLE */
{ "debug-drop-udp-packets", 0, (void*)0L, 'x'},
{ "version", 0, &opt_version, 1},
{ 0, 0, 0, 0},
};
bzero(&loc_addr, sizeof loc_addr);
bzero(&pkt_fd, sizeof pkt_fd);
bzero(&rfd, sizeof rfd);
allow_n_logins = 0;
opt_version = 0;
debug = 0;
daemon_mode = 1;
authorized_users_fname = "/var/urd/authorized_users";
au_fname = "/var/urd/authorized_users";
disable_authorized_users = 0;
pwfile_fname = "/var/urd/passwd";
server_secret_fname = "/var/urd/server_secret";
pid_fname = (char*)0L;
@ -104,30 +146,36 @@ int main(int argc, char **argv)
drop = 1;
drop_mode = 0;
otp_window = OTP_WINDOW_DEFAULT;
pdb_type = PASS_DB_TYPE_LOCAL;
as_name = "urd";
service = "urd";
#ifdef OOTP_ENABLE
otpctx = (struct otp_ctx*)0L;
otpdb_fname = OTP_DB_FNAME;
otp_skip_unknown = 0;
otp_allow_unknown = 0;
otpdb_flags = 0;
otp_enable = 1;
otp_display_count = 0;
#endif /* OOTP_ENABLE */
xerr_setid(argv[0]);
#ifdef OOTP_ENABLE
while ((i = getopt(argc, argv, "AhduDOx?a:b:B:o:p:s:P:w:")) != -1) {
while ((i = getopt_long(argc, argv, "AhduDOx?a:cb:B:mMno:p:s:S:P:V:w:",
longopts, (int*)0L)) != -1) {
#else
while ((i = getopt(argc, argv, "AhdDx?a:b:B:p:s:P:w:")) != -1) {
while ((i = getopt_long(argc, argv, "AhdDx?a:b:B:mMnp:s:S:P:V:",
longopts, (int*)0L)) != -1) {
#endif /* OOTP_ENABLE */
switch (i) {
case 'a':
authorized_users_fname = optarg;
au_fname = optarg;
break;
case 'A':
authorized_users_fname = (char*)0L;
disable_authorized_users = 1;
break;
case 'b':
@ -144,6 +192,10 @@ int main(int argc, char **argv)
local_port = tmpul;
break;
case 'c':
otp_display_count = 1;
break;
case 'd':
debug ++;
#ifdef OOTP_ENABLE
@ -156,11 +208,23 @@ int main(int argc, char **argv)
break;
case 'h':
case '"':
case '?':
usage();
exit(0);
break;
case 'm':
pdb_type = PASS_DB_TYPE_PAM;
break;
case 'M': /* xxx only here for compatability */
disable_authorized_users = 1;
break;
case 'n':
allow_n_logins = 1;
break;
#ifdef OOTP_ENABLE
case 'o':
otpdb_fname = optarg;
@ -183,11 +247,18 @@ int main(int argc, char **argv)
server_secret_fname = optarg;
break;
case 'S':
as_name = optarg;
break;
case 'V':
service = optarg;
break;
#ifdef OOTP_ENABLE
case 'u':
otp_skip_unknown = 1;
otp_allow_unknown = 1;
break;
#endif /* OOTP_ENABLE */
case 'w':
tmpul = strtoul(optarg, &endptr, 0);
@ -197,14 +268,24 @@ int main(int argc, char **argv)
xerr_errx(1, "Challenge window %lu > %lu.", tmpul, OTP_WINDOW_MAX);
otp_window = tmpul;
break;
#endif /* OOTP_ENABLE */
case 'x':
drop_mode = 1;
break;
case 0:
if (opt_version) {
printf("%s\n", ootp_version);
exit(0);
}
default:
xerr_errx(1, "getopt_long(): fatal.");
} /* switch */
} /* while getopt() */
} /* while getopt_long() */
if (daemon_mode) {
@ -216,10 +297,10 @@ int main(int argc, char **argv)
} /* daemon_mode */
buf_l = snprintf(buf, 1024, "urd start:");
buf_l = snprintf(buf, sizeof(buf), "urd start:");
if (debug) {
for (i = 0; i < argc; ++i)
buf_l += snprintf(buf+buf_l, 1024-buf_l, " %s", argv[i]);
buf_l += snprintf(buf+buf_l, sizeof(buf)-buf_l, " %s", argv[i]);
}
xerr_info(buf);
@ -233,12 +314,12 @@ int main(int argc, char **argv)
if (local_ip || (local_port != URD_PORT)) {
buf_l = snprintf(buf, 1024,
buf_l = snprintf(buf, sizeof(buf),
"/var/urd/pid.%s.%d", inet_ntoa(loc_addr.sin_addr), (int)local_port);
} else {
buf_l = snprintf(buf, 1024, "/var/urd/pid");
buf_l = snprintf(buf, sizeof(buf), "/var/urd/pid");
}
@ -255,10 +336,28 @@ int main(int argc, char **argv)
URD_SECRET_LEN+1) < 0)
xerr_errx(1, "server_secret_load(%s): fatal", server_secret_fname);
/* location is password file or pam service name */
if (pdb_type == PASS_DB_TYPE_LOCAL)
loc = pwfile_fname;
else if (pdb_type == PASS_DB_TYPE_PAM)
loc = as_name;
else
xerr_errx(1, "loc fatal, pdb_type=%d", pdb_type);
/* disable authorized users? */
if (disable_authorized_users) {
if (pdb_type == PASS_DB_TYPE_LOCAL)
pdb_type = PASS_DB_TYPE_EX_LOCAL;
else if (pdb_type == PASS_DB_TYPE_PAM)
pdb_type = PASS_DB_TYPE_EX_PAM;
else
xerr_errx(1, "au fatal, pdb_type=%d", pdb_type);
}
/* setup password database */
if (!(pdbctx = pass_db_ctx_new(pwfile_fname, authorized_users_fname)))
if (!(pdbctx = pass_db_ctx_new(loc, au_fname, pdb_type)))
xerr_errx(1, "pass_db_ctx_new(%s,%s): fatal", pwfile_fname,
authorized_users_fname);
au_fname);
pass_db_debug(pdbctx, debug);
@ -338,7 +437,7 @@ int main(int argc, char **argv)
* req_cache lookup:
* hit :
* rep_code and state_counter from cache
* rep_msg from cache XXX future
* rep_msg from cache
* miss :
* state_cache lookup :
* hit :
@ -392,6 +491,7 @@ int main(int argc, char **argv)
rep_state = 0LL;
rep_enc_flags = 0;
rep_cache_flags = 0;
rep_otp_count = 0;
/* initial no state access request */
if (!urdctx->req.tlv_State) {
@ -400,7 +500,8 @@ int main(int argc, char **argv)
xerr_info("req: (no state)");
/* first check the cache for a previously composed reply */
if ((r = urd_req_cache_lookup(urdctx, &rep_code, &rep_state)) < 0)
if ((r = urd_req_cache_lookup(urdctx, &rep_code, &rep_state,
&rep_otp_count, &tmp_cache_flags)) < 0)
xerr_errx(1, "urd_req_cache_lookup(): fatal");
/* hit, then skip to response gen */
@ -415,7 +516,10 @@ int main(int argc, char **argv)
} else if (rep_code == RADIUS_CODE_ACCESS_CHALLENGE) {
rep_enc_flags = URD_ENCODE_FLAG_STATE|URD_ENCODE_FLAG_MSG;
rep_enc_flags = URD_ENCODE_FLAG_STATE;
if (tmp_cache_flags & URD_CACHE_FLAG_MSG)
rep_enc_flags |= URD_ENCODE_FLAG_MSG;
}
@ -431,11 +535,11 @@ int main(int argc, char **argv)
}
/* default to reject */
/* cache lookup invalid, default to ACCESS_REJECT */
rep_code = RADIUS_CODE_ACCESS_REJECT;
/* check password database */
if ((r = pass_db_auth(pdbctx, urdctx->req.user_name,
/* authenticate user */
if ((r = pass_db_auth(pdbctx, URDCTX_USER_NAME,
urdctx->req.user_pass)) < 0)
xerr_errx(1, "pass_db_auth(): fatal");
@ -492,12 +596,12 @@ int main(int argc, char **argv)
goto access_request_rep;
#else /* OOTP_ENABLE */
/*
* if one time passwords are disabled, then the password
* check above meets auth requirements, reply with ACCEPT
* if one time passwords are disabled then the password
* check above meets auth requirements. Reply with ACCESS_ACCEPT.
*
*/
if (!otp_enable) {
rep_code = RADIUS_CODE_ACCESS_ACCEPT;
@ -511,22 +615,67 @@ int main(int argc, char **argv)
/*
* check OTP
*/
if ((r = otp_user_exists(otpctx, urdctx->req.user_name)) < 0)
if ((r = otp_user_exists(otpctx, URDCTX_USER_NAME)) < 0)
xerr_errx(1, "otp_user_exists(): fail.");
/* if user does not exist and not okay to skip OTP users then fail */
if ((r == 1) && (otp_skip_unknown == 0)) {
/*
* if user does not exist and not okay to allow non OTP users
* then authentication request fails with default ACCESS_REJECT.
*/
if ((r == 1) && (otp_allow_unknown == 0)) {
if (debug)
xerr_info("req: fail via otp_user_exists() skip_unknown=0");
xerr_info("req: fail via otp_user_exists() allow_unknown=0");
/* reply with an REJECT */
rep_code = RADIUS_CODE_ACCESS_REJECT;
rep_enc_flags = 0x0;
goto access_request_rep;
}
if (otp_urec_open(otpctx, urdctx->req.user_name, &ou,
/*
* if user does not exist in database and okay to allow non OTP
* users then authentication request is successful without OTP.
* password check was done above, reply with ACCEPT
*/
if ((r == 1) && (otp_allow_unknown == 1)) {
if (debug)
xerr_info("req: pass via otp_user_exists() allow_unknown=1");
/* reply with an ACCEPT, no state, no challenge message */
rep_code = RADIUS_CODE_ACCESS_ACCEPT;
rep_enc_flags = 0x0;
goto access_request_rep;
}
/*
* unknown response from otp_user_exists()
*/
if (r != 0) {
if (debug)
xerr_info("otp_user_exists() unknown response r=%d", r);
/* reply with an REJECT */
rep_code = RADIUS_CODE_ACCESS_REJECT;
rep_enc_flags = 0x0;
goto access_request_rep;
}
if (otp_urec_open(otpctx, URDCTX_USER_NAME, &ou,
O_RDONLY, FFDB_OP_LOCK_EX) < 0)
xerr_errx(1, "otp_urec_open(%s): failed.", urdctx->req.user_name);
xerr_errx(1, "otp_urec_open(%s): failed.", URDCTX_USER_NAME);
if (otp_urec_get(otpctx, &ou) < 0)
xerr_errx(1, "otp_urec_get(): failed.");
@ -534,7 +683,7 @@ int main(int argc, char **argv)
if (otp_urec_close(otpctx, &ou) < 0)
xerr_errx(1, "otp_urec_close(): failed.");
/* disabled user is rejected */
/* disabled user defaults to ACCESS_REJECT */
if (ou.status == OTP_STATUS_DISABLED) {
if (debug)
@ -579,12 +728,26 @@ int main(int argc, char **argv)
/* reply with challenge, challenge message, new state */
rep_code = RADIUS_CODE_ACCESS_CHALLENGE;
rep_enc_flags = URD_ENCODE_FLAG_STATE|URD_ENCODE_FLAG_MSG;
rep_enc_flags = URD_ENCODE_FLAG_STATE;
rep_state = ++urdctx->state_counter;
rep_otp_count = ou.count;
rep_cache_flags = URD_CACHE_FLAG_STATE;
if (otp_display_count || ou.flags & OTP_FLAGS_DSPCNT) {
rep_enc_flags |= URD_ENCODE_FLAG_MSG;
rep_cache_flags |= URD_CACHE_FLAG_MSG;
}
if (ou.flags & OTP_FLAGS_SEND_TOKEN) {
if (otp_user_send_token(otpctx, URDCTX_USER_NAME, service) < 0)
xerr_warnx("otp_user_send_token(): failed.");
}
if (debug)
xerr_info("req: pass via otp_user_get() (active)");
@ -606,9 +769,6 @@ int main(int argc, char **argv)
/* reply with inbound state */
rep_state = urdctx->req.state_counter;
/* default to reject */
rep_code = RADIUS_CODE_ACCESS_REJECT;
if (debug)
xerr_info("req: state set, nothing to do, REJECT.");
@ -621,7 +781,8 @@ int main(int argc, char **argv)
if (debug)
xerr_info("req: (state)");
if ((r = urd_req_cache_lookup(urdctx, &rep_code, &rep_state)) < 0)
if ((r = urd_req_cache_lookup(urdctx, &rep_code, &rep_state,
&rep_otp_count, &tmp_cache_flags)) < 0)
xerr_errx(1, "urd_req_cache_lookup(): fatal");
/* hit, then skip to response gen */
@ -641,12 +802,12 @@ int main(int argc, char **argv)
}
/* cache lookup invalid, default to ACCESS_REJECT */
rep_code = RADIUS_CODE_ACCESS_REJECT;
/* reply with inbound state */
rep_state = urdctx->req.state_counter;
/* default to reject */
rep_code = RADIUS_CODE_ACCESS_REJECT;
/*
* state cache lookup -- user must have previously authenticated
* successfully to continue
@ -660,6 +821,9 @@ int main(int argc, char **argv)
if (debug)
xerr_info("state: cache miss (user not validated with passwd)");
/* cache lookup invalid, default to ACCESS_REJECT */
rep_code = RADIUS_CODE_ACCESS_REJECT;
goto access_request_rep;
} else {
@ -680,12 +844,13 @@ int main(int argc, char **argv)
}
/*
* default to reject. State cache lookup will have CHALLENGE
* code as it is shared with the request cache.
* default to ACCESS_REJECT. State cache lookup will have
* ACCESS_CHALLENGE code as it is shared with the request cache.
*/
rep_code = RADIUS_CODE_ACCESS_REJECT;
if ((r = otp_user_exists(otpctx, urdctx->req.user_name)) < 0)
if ((r = otp_user_exists(otpctx, URDCTX_USER_NAME)) < 0)
xerr_errx(1, "otp_user_exists(): fail.");
/* user exist?, if not failure */
@ -699,9 +864,9 @@ int main(int argc, char **argv)
}
if (otp_urec_open(otpctx, urdctx->req.user_name, &ou,
if (otp_urec_open(otpctx, URDCTX_USER_NAME, &ou,
O_RDONLY, FFDB_OP_LOCK_EX) < 0)
xerr_errx(1, "otp_urec_open(%s): failed.", urdctx->req.user_name);
xerr_errx(1, "otp_urec_open(%s): failed.", URDCTX_USER_NAME);
if (otp_urec_get(otpctx, &ou) < 0)
xerr_errx(1, "otp_urec_get(): failed.");
@ -730,7 +895,7 @@ int main(int argc, char **argv)
}
if ((r = otp_user_auth(otpctx, urdctx->req.user_name,
if ((r = otp_user_auth(otpctx, URDCTX_USER_NAME,
urdctx->req.user_pass, otp_window)) < 0)
xerr_errx(1, "otp_user_auth(): failed.");
@ -781,12 +946,13 @@ access_request_rep:
* construct reply
*/
if (urd_rep_encode(urdctx, rep_code, rep_state, rep_enc_flags) < 0) {
if (urd_rep_encode(urdctx, rep_code, rep_state, rep_otp_count,
rep_enc_flags) < 0) {
xerr_errx(1, "urd_rep_encode(): fatal");
}
/* update reply cache */
if (urd_req_cache_update(urdctx, rep_code, rep_state,
if (urd_req_cache_update(urdctx, rep_code, rep_state, rep_otp_count,
rep_cache_flags) < 0)
xerr_errx(1, "urd_req_cache_update(): fatal");
@ -973,7 +1139,7 @@ int write_pidfile(char *fname)
int fd, buf_l;
char buf[512];
buf_l = snprintf(buf, 512, "%lu\n", (unsigned long)getpid());
buf_l = snprintf(buf, sizeof(buf), "%lu\n", (unsigned long)getpid());
if ((fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0 ) {
xerr_warn("open(%s)", fname);
@ -998,21 +1164,23 @@ void usage(void)
{
#ifdef OOTP_ENABLE
fprintf(stderr,
"urd [-AhdDOux?] [-a allowed_users_file] [-b local_ip] [-B local_port ]\n");
"urd [-AhcdDmMnOux?] [-a allowed_users_file] [-b local_ip] [-B local_port ]\n");
fprintf(stderr,
" [-o otp_db] [-p passwd_file] [-P pid_file] [-s secret_file]\n");
#else
fprintf(stderr,
"urd [-AhdDx?] [-a allowed_users_file] [-b local_ip] [-B local_port ]\n");
"urd [-AdDmMnhx?] [-a allowed_users_file] [-b local_ip] [-B local_port ]\n");
fprintf(stderr,
" [-p passwd_file] [-P pid_file] [-s secret_file]\n");
#endif /* OOTP_ENABLE */
fprintf(stderr, " [-w otp_window]\n\n");
fprintf(stderr, " [-S auth_service_name] [-w otp_window]\n\n");
fprintf(stderr, " -A disable authorized_users file (all users in passwd_file valid)\n");
fprintf(stderr, " -h help\n");
fprintf(stderr, " -d enable debugging\n");
fprintf(stderr, " -D disable daemon mode\n");
fprintf(stderr, " -m use PAM for password authentication\n");
fprintf(stderr, " -M use PAM exclusively for password authentication\n");
#ifdef OOTP_ENABLE
fprintf(stderr, " -O disable one time passwords\n");
fprintf(stderr, " -u allow users which do not exist in OTP database\n");