WIP: OATH module
git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@623 185d5e19-27fe-0310-9dcf-9bff6b9f3609
This commit is contained in:
parent
4978bcf862
commit
2546d3cf58
1
CREDITS
1
CREDITS
|
@ -21,6 +21,7 @@ ideas:
|
|||
Don Lewis <truckman@freebsd.org>
|
||||
Emmanuel Dreyfus <manu@netbsd.org>
|
||||
Eric Melville <eric@freebsd.org>
|
||||
Espen Grøndahl <espegro@usit.uio.no>
|
||||
Gary Winiger <gary.winiger@sun.com>
|
||||
Gleb Smirnoff <glebius@freebsd.org>
|
||||
Hubert Feyrer <hubert@feyrer.de>
|
||||
|
|
|
@ -13,6 +13,7 @@ export CONFIG_SHELL=/bin/sh
|
|||
./configure \
|
||||
--with-doc \
|
||||
--with-pam-unix \
|
||||
--with-pam-oath \
|
||||
--with-pamtest \
|
||||
--with-su \
|
||||
--with-modules-dir=/usr/lib \
|
||||
|
|
16
configure.ac
16
configure.ac
|
@ -64,11 +64,17 @@ AC_ARG_WITH([doc],
|
|||
AM_CONDITIONAL([WITH_DOC], [test x"$with_doc" = x"yes"])
|
||||
|
||||
AC_ARG_WITH([pam-unix],
|
||||
AC_HELP_STRING([--with-pam-unix], [compile sample pam_unix(8) implementation]),
|
||||
AC_HELP_STRING([--with-pam-unix], [compile sample pam_unix(8) module]),
|
||||
[],
|
||||
[with_pam_unix=no])
|
||||
AM_CONDITIONAL([WITH_PAM_UNIX], [test x"$with_pam_unix" = x"yes"])
|
||||
|
||||
AC_ARG_WITH([pam-oath],
|
||||
AC_HELP_STRING([--with-pam-oath], [compile pam_oath(8) module]),
|
||||
[],
|
||||
[with_pam_oath=no])
|
||||
AM_CONDITIONAL([WITH_PAM_OATH], [test x"$with_pam_oath" = x"yes"])
|
||||
|
||||
AC_ARG_WITH(pamtest,
|
||||
AC_HELP_STRING([--with-pamtest], [compile test application]),
|
||||
[],
|
||||
|
@ -99,6 +105,13 @@ CRYPT_LIBS="${LIBS}"
|
|||
LIBS="${saved_LIBS}"
|
||||
AC_SUBST(CRYPT_LIBS)
|
||||
|
||||
saved_LIBS="${LIBS}"
|
||||
LIBS=""
|
||||
AC_CHECK_LIB([crypto], [OpenSSL_add_all_algorithms])
|
||||
CRYPTO_LIBS="${LIBS}"
|
||||
LIBS="${saved_LIBS}"
|
||||
AC_SUBST(CRYPTO_LIBS)
|
||||
|
||||
AC_ARG_ENABLE([developer-warnings],
|
||||
AS_HELP_STRING([--enable-developer-warnings], [enable strict warnings (default is NO)]),
|
||||
[CFLAGS="${CFLAGS} -Wall -Wextra"])
|
||||
|
@ -124,6 +137,7 @@ AC_CONFIG_FILES([
|
|||
modules/pam_deny/Makefile
|
||||
modules/pam_permit/Makefile
|
||||
modules/pam_unix/Makefile
|
||||
modules/pam_oath/Makefile
|
||||
t/Makefile
|
||||
])
|
||||
AC_CONFIG_FILES([pamgdb],[chmod +x pamgdb])
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# $Id$
|
||||
|
||||
SUBDIRS = pam_unix pam_deny pam_permit
|
||||
SUBDIRS = pam_deny pam_permit
|
||||
SUBDIRS += pam_unix
|
||||
SUBDIRS += pam_oath
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
# $Id: Makefile.am 429 2010-03-09 17:51:29Z des $
|
||||
|
||||
pkglibdir = @OPENPAM_MODULES_DIR@
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/include
|
||||
|
||||
if WITH_PAM_OATH
|
||||
pkglib_LTLIBRARIES = pam_oath.la
|
||||
|
||||
noinst_HEADERS = oath.h
|
||||
pam_oath_la_SOURCES = pam_oath.c oath_hotp.c oath_totp.c
|
||||
pam_oath_la_LDFLAGS = -no-undefined -module -version-info @LIB_MAJ@ \
|
||||
-export-symbols-regex '^pam_sm_'
|
||||
pam_oath_la_LIBADD = $(top_builddir)/lib/libpam.la @CRYPTO_LIBS@
|
||||
endif
|
|
@ -0,0 +1,57 @@
|
|||
/*-
|
||||
* Copyright (c) 2012-2013 Universitetet i Oslo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef OATH_H_INCLUDED
|
||||
#define OATH_H_INCLUDED
|
||||
|
||||
#define base32_enclen(l) (((l + 4) / 5) * 8)
|
||||
#define base32_declen(l) (((l + 7) / 8) * 5)
|
||||
int base32_enc(const uint8_t *, size_t, char *, size_t *);
|
||||
int base32_dec(const char *, size_t, uint8_t *, size_t *);
|
||||
|
||||
#define base64_enclen(l) (((l + 2) / 3) * 4)
|
||||
#define base64_declen(l) (((l + 3) / 4) * 3)
|
||||
int base64_enc(const uint8_t *, size_t, char *, size_t *);
|
||||
int base64_dec(const char *, size_t, uint8_t *, size_t *);
|
||||
|
||||
enum oath_alg { undef, hotp, totp };
|
||||
|
||||
struct oath {
|
||||
enum oath_alg alg;
|
||||
unsigned int seq;
|
||||
size_t keylen;
|
||||
uint8_t key[];
|
||||
};
|
||||
|
||||
unsigned int oath_hotp(const uint8_t *, size_t, uint64_t, unsigned int);
|
||||
unsigned int oath_totp(const uint8_t *, size_t, unsigned int);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,161 @@
|
|||
/*-
|
||||
* Copyright (c) 2013 Universitetet i Oslo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "oath.h"
|
||||
|
||||
static const char b32 =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
/*
|
||||
* Encode data in RFC 3548 base 32 representation. The target buffer must
|
||||
* have room for base32_enclen(len) characters and a terminating NUL.
|
||||
*/
|
||||
int
|
||||
base32_enc(const uint8_t *in, size_t ilen, char *out, size_t *olen)
|
||||
{
|
||||
uint64_t bits;
|
||||
|
||||
if (*olen <= base32_enclen(ilen))
|
||||
return (-1);
|
||||
*olen = 0;
|
||||
while (ilen >= 5) {
|
||||
bits = 0;
|
||||
bits |= (uint64_t)in[0] << 32;
|
||||
bits |= (uint64_t)in[1] << 24;
|
||||
bits |= (uint64_t)in[2] << 16;
|
||||
bits |= (uint64_t)in[3] << 8;
|
||||
bits |= (uint64_t)in[4];
|
||||
ilen -= 5;
|
||||
in += 5;
|
||||
out[0] = b32[bits >> 35 & 0x1f];
|
||||
out[1] = b32[bits >> 30 & 0x1f];
|
||||
out[2] = b32[bits >> 25 & 0x1f];
|
||||
out[3] = b32[bits >> 20 & 0x1f];
|
||||
out[4] = b32[bits >> 15 & 0x1f];
|
||||
out[5] = b32[bits >> 10 & 0x1f];
|
||||
out[6] = b32[bits >> 5 & 0x1f];
|
||||
out[7] = b32[bits & 0x1f];
|
||||
olen += 8;
|
||||
out += 8;
|
||||
}
|
||||
if (ilen > 0) {
|
||||
bits = 0;
|
||||
switch (ilen) {
|
||||
case 4:
|
||||
bits |= (uint64_t)in[3] << 8;
|
||||
case 3:
|
||||
bits |= (uint64_t)in[2] << 16;
|
||||
case 2:
|
||||
bits |= (uint64_t)in[1] << 24;
|
||||
case 1:
|
||||
bits |= (uint64_t)in[0] << 32;
|
||||
}
|
||||
out[0] = b32[bits >> 35 & 0x1f];
|
||||
out[1] = b32[bits >> 30 & 0x1f];
|
||||
out[2] = ilen > 1 ? b32[bits >> 25 & 0x1f] : '=';
|
||||
out[3] = ilen > 1 ? b32[bits >> 20 & 0x1f] : '=';
|
||||
out[4] = ilen > 2 ? b32[bits >> 15 & 0x1f] : '=';
|
||||
out[5] = ilen > 3 ? b32[bits >> 10 & 0x1f] : '=';
|
||||
out[6] = ilen > 3 ? b32[bits >> 5 & 0x1f] : '=';
|
||||
out[7] = '=';
|
||||
olen += 8;
|
||||
out += 8;
|
||||
}
|
||||
out[0] = '\0';
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode data in RFC 2548 base 32 representation, stopping at the
|
||||
* terminating NUL, the first invalid (non-base32, non-whitespace)
|
||||
* character or after len characters, whichever comes first.
|
||||
*
|
||||
* The olen argument is used by the caller to pass the size of the buffer
|
||||
* and by base32_dec() to return the amount of data successfully decoded.
|
||||
* If the buffer is too small, base32_dec() discards the excess data, but
|
||||
* returns the total amount.
|
||||
*/
|
||||
int
|
||||
base32_dec(const char *in, size_t ilen, uint8_t *out, size_t *olen)
|
||||
{
|
||||
size_t len;
|
||||
uint64_t bits;
|
||||
int shift;
|
||||
|
||||
for (len = 0, bits = 0, shift = 40; ilen && *in; --ilen, ++in) {
|
||||
if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n') {
|
||||
continue;
|
||||
} else if (*in >= 'A' && *in <= 'Z') {
|
||||
shift -= 5;
|
||||
bits |= (uint64_t)(*in - 'A') << shift;
|
||||
} else if (*in >= 'a' && *in <= 'z') {
|
||||
shift -= 5;
|
||||
bits |= (uint64_t)(*in - 'a') << shift;
|
||||
} else if (*in >= '2' && *in <= '7') {
|
||||
shift -= 5;
|
||||
bits |= (uint64_t)(*in - '2' + 26) << shift;
|
||||
} else if (*in == '=' &&
|
||||
(shift == 30 || shift == 20 || shift == 15 || shift == 5)) {
|
||||
/* hack: assume the rest of the padding is ok */
|
||||
shift = 0;
|
||||
} else {
|
||||
*olen = 0;
|
||||
return (-1);
|
||||
}
|
||||
if (shift == 0) {
|
||||
if ((len += 5) <= *olen) {
|
||||
out[0] = (bits >> 32) & 0xff;
|
||||
out[1] = (bits >> 24) & 0xff;
|
||||
out[2] = (bits >> 16) & 0xff;
|
||||
out[3] = (bits >> 8) & 0xff;
|
||||
out[4] = bits & 0xff;
|
||||
out += 5;
|
||||
}
|
||||
bits = 0;
|
||||
shift = 40;
|
||||
}
|
||||
if (*in == '=')
|
||||
break;
|
||||
}
|
||||
if (len > *olen) {
|
||||
*olen = len;
|
||||
return (-1);
|
||||
}
|
||||
*olen = len;
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,152 @@
|
|||
/*-
|
||||
* Copyright (c) 2013 Universitetet i Oslo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "oath.h"
|
||||
|
||||
static const char b64 =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
/*
|
||||
* Encode data in RFC 3548 base 64 representation. The target buffer must
|
||||
* have room for base64_enclen(len) characters and a terminating NUL.
|
||||
*/
|
||||
int
|
||||
base64_enc(const uint8_t *in, size_t ilen, char *out, size_t *olen)
|
||||
{
|
||||
uint32_t bits;
|
||||
|
||||
if (*olen <= base64_enclen(ilen))
|
||||
return (-1);
|
||||
*olen = 0;
|
||||
while (ilen >= 3) {
|
||||
bits = 0;
|
||||
bits |= (uint32_t)in[0] << 16;
|
||||
bits |= (uint32_t)in[1] << 8;
|
||||
bits |= (uint32_t)in[2];
|
||||
ilen -= 3;
|
||||
in += 3;
|
||||
out[0] = b64[bits >> 18 & 0x3f];
|
||||
out[1] = b64[bits >> 12 & 0x3f];
|
||||
out[2] = b64[bits >> 6 & 0x3f];
|
||||
out[3] = b64[bits & 0x3f];
|
||||
olen += 4;
|
||||
out += 4;
|
||||
}
|
||||
if (ilen > 0) {
|
||||
bits = 0;
|
||||
switch (ilen) {
|
||||
case 2:
|
||||
bits |= (uint32_t)in[1] << 8;
|
||||
case 1:
|
||||
bits |= (uint32_t)in[0] << 16;
|
||||
}
|
||||
out[0] = b64[bits >> 18 & 0x1f];
|
||||
out[1] = b64[bits >> 12 & 0x1f];
|
||||
out[2] = ilen > 1 ? b64[bits >> 6 & 0x1f] : '=';
|
||||
out[3] = '=';
|
||||
olen += 4;
|
||||
out += 4;
|
||||
}
|
||||
out[0] = '\0';
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode data in RFC 2548 base 64 representation, stopping at the
|
||||
* terminating NUL, the first invalid (non-base64, non-whitespace)
|
||||
* character or after len characters, whichever comes first.
|
||||
*
|
||||
* The olen argument is used by the caller to pass the size of the buffer
|
||||
* and by base64_dec() to return the amount of data successfully decoded.
|
||||
* If the buffer is too small, base64_dec() discards the excess data, but
|
||||
* returns the total amount.
|
||||
*/
|
||||
int
|
||||
base64_dec(const char *in, size_t ilen, uint8_t *out, size_t *olen)
|
||||
{
|
||||
size_t len;
|
||||
uint32_t bits;
|
||||
int shift;
|
||||
|
||||
for (len = 0, bits = 0, shift = 24; ilen && *in; --ilen, ++in) {
|
||||
if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n') {
|
||||
continue;
|
||||
} else if (*in >= 'A' && *in <= 'Z') {
|
||||
shift -= 6;
|
||||
bits |= (uint32_t)(*in - 'A') << shift;
|
||||
} else if (*in >= 'a' && *in <= 'z') {
|
||||
shift -= 6;
|
||||
bits |= (uint32_t)(*in - 'a' + 26) << shift;
|
||||
} else if (*in >= '0' && *in <= '9') {
|
||||
shift -= 6;
|
||||
bits |= (uint32_t)(*in - '2' + 52) << shift;
|
||||
} else if (*in == '+') {
|
||||
shift -= 6;
|
||||
bits |= (uint32_t)62 << shift;
|
||||
} else if (*in == '/') {
|
||||
shift -= 6;
|
||||
bits |= (uint32_t)63 << shift;
|
||||
} else if (*in == '=' && (shift == 12 || shift == 6)) {
|
||||
/* hack: assume the rest of the padding is ok */
|
||||
shift = 0;
|
||||
} else {
|
||||
*olen = 0;
|
||||
return (-1);
|
||||
}
|
||||
if (shift == 0) {
|
||||
if ((len += 3) <= *olen) {
|
||||
out[1] = (bits >> 16) & 0xff;
|
||||
out[1] = (bits >> 8) & 0xff;
|
||||
out[2] = bits & 0xff;
|
||||
out += 3;
|
||||
}
|
||||
bits = 0;
|
||||
shift = 24;
|
||||
}
|
||||
if (*in == '=')
|
||||
break;
|
||||
}
|
||||
if (len > *olen) {
|
||||
*olen = len;
|
||||
return (-1);
|
||||
}
|
||||
*olen = len;
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*-
|
||||
* Copyright (c) 2012-2013 Universitetet i Oslo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/hmac.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "oath.h"
|
||||
|
||||
#define StToNum(St) (St)
|
||||
|
||||
static uint32_t
|
||||
DT(const uint8_t *String)
|
||||
{
|
||||
uint8_t OffsetBits;
|
||||
int Offset;
|
||||
uint32_t P;
|
||||
|
||||
OffsetBits = String[19] & 0x0f;
|
||||
Offset = StToNum(OffsetBits);
|
||||
P = (uint32_t)String[Offset + 0] << 24 |
|
||||
(uint32_t)String[Offset + 1] << 16 |
|
||||
(uint32_t)String[Offset + 2] << 8 |
|
||||
(uint32_t)String[Offset + 3];
|
||||
return (P & 0x7fffffffUL);
|
||||
}
|
||||
|
||||
unsigned int
|
||||
oath_hotp(const uint8_t *K, size_t Klen, uint64_t seq, unsigned int Digit)
|
||||
{
|
||||
HMAC_CTX ctx;
|
||||
uint8_t C[8];
|
||||
uint8_t HS[20];
|
||||
unsigned int HSlen;
|
||||
uint32_t Sbits, Snum;
|
||||
unsigned int mod, D;
|
||||
|
||||
for (int i = 7; i >= 0; --i) {
|
||||
C[i] = seq & 0xff;
|
||||
seq >>= 8;
|
||||
}
|
||||
|
||||
/* HS = HMAC-SHA-1(K,C) */
|
||||
HMAC_CTX_init(&ctx);
|
||||
HMAC_Init_ex(&ctx, K, Klen, EVP_sha1(), NULL);
|
||||
HMAC_Update(&ctx, (const uint8_t *)&C, sizeof C);
|
||||
HMAC_Final(&ctx, HS, &HSlen);
|
||||
HMAC_CTX_cleanup(&ctx);
|
||||
|
||||
Sbits = DT(HS);
|
||||
Snum = StToNum(Sbits);
|
||||
for (mod = 1; Digit > 0; --Digit)
|
||||
mod *= 10;
|
||||
D = Snum % mod;
|
||||
return (D);
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/*-
|
||||
* Copyright (c) 2013 Universitetet i Oslo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "oath.h"
|
||||
|
||||
/* amount of space necessary to store base32-encoded data */
|
||||
#define base32_enclen(l) (((l + 4) / 5) * 8)
|
||||
|
||||
/* maximum decoded length of base32-encoded data */
|
||||
#define base32_declen(l) (((l + 7) / 8) * 5)
|
||||
|
||||
static const char b32 =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
/*
|
||||
* Encode data in RFC 3548 base 32 representation. The target buffer must
|
||||
* have room for base32_enclen(len) characters and a terminating NUL.
|
||||
*/
|
||||
static int
|
||||
base32_enc(const uint8_t *in, size_t ilen, char *out, size_t *olen)
|
||||
{
|
||||
uint64_t bits;
|
||||
|
||||
if (*olen <= base32_enclen(ilen))
|
||||
return (-1);
|
||||
*olen = 0;
|
||||
while (ilen >= 5) {
|
||||
bits = 0;
|
||||
bits = bits << 8 | in[0];
|
||||
bits = bits << 8 | in[1];
|
||||
bits = bits << 8 | in[2];
|
||||
bits = bits << 8 | in[3];
|
||||
bits = bits << 8 | in[4];
|
||||
ilen -= 5;
|
||||
in += 5;
|
||||
out[0] = b32[bits >> 5*7 & 0x1f];
|
||||
out[1] = b32[bits >> 5*6 & 0x1f];
|
||||
out[2] = b32[bits >> 5*5 & 0x1f];
|
||||
out[3] = b32[bits >> 5*4 & 0x1f];
|
||||
out[4] = b32[bits >> 5*3 & 0x1f];
|
||||
out[5] = b32[bits >> 5*2 & 0x1f];
|
||||
out[6] = b32[bits >> 5*1 & 0x1f];
|
||||
out[7] = b32[bits >> 5*0 & 0x1f];
|
||||
olen += 8;
|
||||
out += 8;
|
||||
}
|
||||
if (ilen > 0) {
|
||||
bits = 0;
|
||||
switch (ilen) {
|
||||
case 4:
|
||||
bits |= (uint64_t)in[3] << 8;
|
||||
case 3:
|
||||
bits |= (uint64_t)in[2] << 16;
|
||||
case 2:
|
||||
bits |= (uint64_t)in[1] << 24;
|
||||
case 1:
|
||||
bits |= (uint64_t)in[1] << 32;
|
||||
}
|
||||
out[0] = b32[bits >> 5*7 & 0x1f];
|
||||
out[1] = b32[bits >> 5*6 & 0x1f];
|
||||
out[2] = ilen > 1 ? b32[bits >> 5*5 & 0x1f] : '=';
|
||||
out[3] = ilen > 1 ? b32[bits >> 5*4 & 0x1f] : '=';
|
||||
out[4] = ilen > 2 ? b32[bits >> 5*3 & 0x1f] : '=';
|
||||
out[5] = ilen > 3 ? b32[bits >> 5*2 & 0x1f] : '=';
|
||||
out[6] = ilen > 3 ? b32[bits >> 5*1 & 0x1f] : '=';
|
||||
out[7] = '=';
|
||||
olen += 8;
|
||||
out += 8;
|
||||
}
|
||||
out[0] = '\0';
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode data in RFC 2548 base 32 representation, stopping at the
|
||||
* terminating NUL, the first invalid (non-base32, non-whitespace)
|
||||
* character or after len characters, whichever comes first.
|
||||
*
|
||||
* The olen argument is used by the caller to pass the size of the buffer
|
||||
* and by base32_dec() to return the amount of data successfully decoded.
|
||||
* If the buffer is too small, base32_dec() discards the excess data, but
|
||||
* returns the total amount.
|
||||
*/
|
||||
static int
|
||||
base32_dec(const char *in, size_t ilen, uint8_t *out, size_t *olen)
|
||||
{
|
||||
size_t len;
|
||||
uint64_t bits;
|
||||
int shift;
|
||||
|
||||
for (len = 0, bits = 0, shift = 40; ilen && *in; --ilen, ++in) {
|
||||
if (*in == ' ' || *in == '\t' || *in == '\r' || *in == '\n') {
|
||||
continue;
|
||||
} else if (*in >= 'A' && *in <= 'Z') {
|
||||
shift -= 5;
|
||||
bits |= (uint64_t)(*in - 'A') << shift;
|
||||
} else if (*in >= 'a' && *in <= 'z') {
|
||||
shift -= 5;
|
||||
bits |= (uint64_t)(*in - 'a') << shift;
|
||||
} else if (*in >= '2' && *in <= '7') {
|
||||
shift -= 5;
|
||||
bits |= (uint64_t)(*in - '2' + 26) << shift;
|
||||
} else {
|
||||
*olen = 0;
|
||||
return (-1);
|
||||
}
|
||||
if (shift == 0) {
|
||||
if ((len += 5) <= *olen) {
|
||||
out[0] = (bits >> 32) & 0xff;
|
||||
out[1] = (bits >> 24) & 0xff;
|
||||
out[2] = (bits >> 16) & 0xff;
|
||||
out[3] = (bits >> 8) & 0xff;
|
||||
out[4] = bits & 0xff;
|
||||
out += 5;
|
||||
}
|
||||
bits = 0;
|
||||
shift = 40;
|
||||
}
|
||||
}
|
||||
if (len > *olen) {
|
||||
*olen = len;
|
||||
return (-1);
|
||||
}
|
||||
*olen = len;
|
||||
return (0);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/*-
|
||||
* Copyright (c) 2012-2013 Universitetet i Oslo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "oath.h"
|
||||
|
||||
#define TOTP_TIME_STEP 30
|
||||
|
||||
unsigned int
|
||||
oath_totp(const uint8_t *K, size_t Klen, unsigned int Digit)
|
||||
{
|
||||
time_t now;
|
||||
|
||||
time(&now);
|
||||
return (oath_hotp(K, Klen, now / TOTP_TIME_STEP, Digit));
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*-
|
||||
* Copyright (c) 2012-2013 Universitetet i Oslo
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <pwd.h>
|
||||
|
||||
#define PAM_SM_AUTH
|
||||
#define PAM_SM_ACCOUNT
|
||||
|
||||
#include <security/pam_modules.h>
|
||||
#include <security/pam_appl.h>
|
||||
|
||||
PAM_EXTERN int
|
||||
pam_sm_authenticate(pam_handle_t *pamh, int flags,
|
||||
int argc, const char *argv[])
|
||||
{
|
||||
struct passwd *pwd;
|
||||
const char *user;
|
||||
char *password;
|
||||
int pam_err;
|
||||
|
||||
(void)flags;
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
/* identify user */
|
||||
if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
|
||||
return (pam_err);
|
||||
if ((pwd = getpwnam(user)) == NULL)
|
||||
return (PAM_USER_UNKNOWN);
|
||||
|
||||
/* get code */
|
||||
pam_err = pam_get_authtok(pamh, PAM_AUTHTOK,
|
||||
(const char **)&password, NULL);
|
||||
if (pam_err == PAM_CONV_ERR)
|
||||
return (pam_err);
|
||||
if (pam_err != PAM_SUCCESS)
|
||||
return (PAM_AUTH_ERR);
|
||||
|
||||
pam_err = PAM_AUTH_ERR;
|
||||
return (pam_err);
|
||||
}
|
||||
|
||||
PAM_EXTERN int
|
||||
pam_sm_setcred(pam_handle_t *pamh, int flags,
|
||||
int argc, const char *argv[])
|
||||
{
|
||||
|
||||
(void)pamh;
|
||||
(void)flags;
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
|
||||
PAM_EXTERN int
|
||||
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
|
||||
int argc, const char *argv[])
|
||||
{
|
||||
|
||||
(void)pamh;
|
||||
(void)flags;
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return (PAM_SUCCESS);
|
||||
}
|
||||
|
||||
PAM_MODULE_ENTRY("pam_unix");
|
Loading…
Reference in New Issue