mirror of
https://github.com/Yubico/yubico-pam.git
synced 2025-02-26 21:54:15 +01:00
Merge branch 'pr-221'
This commit is contained in:
commit
d468b61caf
2
.github/workflows/codeql-analysis.yml
vendored
2
.github/workflows/codeql-analysis.yml
vendored
@ -32,7 +32,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install -y libykclient-dev libykpers-1-dev libyubikey-dev \
|
sudo apt install -y libykclient-dev libykpers-1-dev libyubikey-dev \
|
||||||
libpam-dev help2man asciidoc-base
|
libpam-dev help2man asciidoc-base libmysqlclient-dev
|
||||||
autoreconf --install
|
autoreconf --install
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
|
2
.github/workflows/scan.yml
vendored
2
.github/workflows/scan.yml
vendored
@ -8,7 +8,7 @@ on:
|
|||||||
env:
|
env:
|
||||||
SCAN_IMG:
|
SCAN_IMG:
|
||||||
yubico-yes-docker-local.jfrog.io/static-code-analysis/c:v1
|
yubico-yes-docker-local.jfrog.io/static-code-analysis/c:v1
|
||||||
COMPILE_DEPS: "libykclient-dev libykpers-1-dev libyubikey-dev"
|
COMPILE_DEPS: "libykclient-dev libykpers-1-dev libyubikey-dev libmysqlclient-dev"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
14
.travis.yml
14
.travis.yml
@ -1,4 +1,3 @@
|
|||||||
sudo: required
|
|
||||||
language: c
|
language: c
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
@ -7,13 +6,14 @@ compiler:
|
|||||||
- gcc
|
- gcc
|
||||||
- clang
|
- clang
|
||||||
env:
|
env:
|
||||||
- CONFIGURE_ARGS="" EXTRA="libldap2-dev libykpers-1-dev libnet-ldap-server-perl"
|
- CONFIGURE_ARGS="" EXTRA="libldap2-dev libykpers-1-dev libnet-ldap-server-perl libmysqlclient-dev"
|
||||||
- CONFIGURE_ARGS="--without-ldap" EXTRA="libykpers-1-dev"
|
- CONFIGURE_ARGS="--without-ldap" EXTRA="libykpers-1-dev libmysqlclient-dev"
|
||||||
- CONFIGURE_ARGS="--without-cr" EXTRA="libldap2-dev libnet-ldap-server-perl"
|
- CONFIGURE_ARGS="--without-cr" EXTRA="libldap2-dev libnet-ldap-server-perl libmysqlclient-dev"
|
||||||
- CONFIGURE_ARGS="--without-ldap --without-cr"
|
- CONFIGURE_ARGS="--without-ldap --without-cr" EXTRA="libmysqlclient-dev"
|
||||||
script: tests/aux/build-and-test.sh
|
script: tests/aux/build-and-test.sh
|
||||||
matrix:
|
jobs:
|
||||||
|
install: travis_wait 30 mvn install
|
||||||
include:
|
include:
|
||||||
- compiler: gcc
|
- compiler: gcc
|
||||||
os: linux
|
os: linux
|
||||||
env: COVERAGE="--enable-coverage" EXTRA="libldap2-dev libykpers-1-dev libnet-ldap-server-perl lcov"
|
env: COVERAGE="--enable-coverage" EXTRA="libldap2-dev libykpers-1-dev libnet-ldap-server-perl lcov libmysqlclient-dev"
|
||||||
|
@ -45,7 +45,12 @@ pam_yubico_la_LDFLAGS = -module -avoid-version
|
|||||||
|
|
||||||
noinst_LTLIBRARIES = libpam_util.la libpam_real.la
|
noinst_LTLIBRARIES = libpam_util.la libpam_real.la
|
||||||
libpam_util_la_SOURCES = util.c util.h
|
libpam_util_la_SOURCES = util.c util.h
|
||||||
libpam_util_la_LIBADD = @LTLIBYUBIKEY@ @YKPERS_LIBS@
|
libpam_util_la_LIBADD = @LTLIBYUBIKEY@ @YKPERS_LIBS@
|
||||||
|
|
||||||
|
# if MYSQL_SUPPORT
|
||||||
|
AM_CFLAGS += @MYSQL_CFLAGS@
|
||||||
|
libpam_util_la_LIBADD += @MYSQL_LIBS@
|
||||||
|
# endif
|
||||||
|
|
||||||
libpam_real_la_SOURCES = pam_yubico.c
|
libpam_real_la_SOURCES = pam_yubico.c
|
||||||
|
|
||||||
|
13
configure.ac
13
configure.ac
@ -75,6 +75,19 @@ AC_ARG_WITH([ldap],
|
|||||||
[libldap not found, will not be compiled (--without-ldap to disable ldap support)])],
|
[libldap not found, will not be compiled (--without-ldap to disable ldap support)])],
|
||||||
[])])
|
[])])
|
||||||
|
|
||||||
|
AC_ARG_WITH([mysql],
|
||||||
|
[AS_HELP_STRING([--without-mysql],
|
||||||
|
[disable support for mysql])],
|
||||||
|
[],
|
||||||
|
[with_mysql=yes])
|
||||||
|
AS_IF([test "x$with_mysql" != xno],
|
||||||
|
[
|
||||||
|
PKG_CHECK_MODULES([MYSQL], [mysqlclient],
|
||||||
|
[AC_DEFINE([HAVE_MYSQL], [1],[Define if you have mysqlclient])],
|
||||||
|
[AC_MSG_WARN(
|
||||||
|
[libmysqlclient not found, will not be compiled (--without-mysql to disable mysql support)])])
|
||||||
|
])
|
||||||
|
AM_CONDITIONAL(MYSQL_SUPPORT,test "x$with_mysql" != xno)
|
||||||
|
|
||||||
AC_LIB_HAVE_LINKFLAGS([ykclient],, [#include <ykclient.h>],
|
AC_LIB_HAVE_LINKFLAGS([ykclient],, [#include <ykclient.h>],
|
||||||
[ykclient_set_proxy(0, 0)])
|
[ykclient_set_proxy(0, 0)])
|
||||||
|
@ -116,6 +116,18 @@ CA certitificate file for the LDAP connection.
|
|||||||
*chalresp_path*=_path_::
|
*chalresp_path*=_path_::
|
||||||
Path of a system-wide directory where challenge-response files can be found for users. Default location is `$HOME/.yubico/`.
|
Path of a system-wide directory where challenge-response files can be found for users. Default location is `$HOME/.yubico/`.
|
||||||
|
|
||||||
|
*mysql_server*=_mysqlserver_::
|
||||||
|
Hostname/Adress of mysql server. Example 10.0.0.1
|
||||||
|
|
||||||
|
*mysql_user*=_mysqluser_::
|
||||||
|
User for accessing to the database. Strongly recommended to use a specific user with read only access.
|
||||||
|
|
||||||
|
*mysql_password*=_mysqlpassword_::
|
||||||
|
Mysql password associated to the user.
|
||||||
|
|
||||||
|
*mysql_database*=_mysqldatabase_::
|
||||||
|
the name of the database. Example : otp
|
||||||
|
|
||||||
== EXAMPLES
|
== EXAMPLES
|
||||||
|
|
||||||
auth sufficient pam_yubico.so id=16 debug
|
auth sufficient pam_yubico.so id=16 debug
|
||||||
|
32
pam_yubico.c
32
pam_yubico.c
@ -134,6 +134,11 @@ struct cfg
|
|||||||
const char *user_attr;
|
const char *user_attr;
|
||||||
const char *yubi_attr;
|
const char *yubi_attr;
|
||||||
const char *yubi_attr_prefix;
|
const char *yubi_attr_prefix;
|
||||||
|
const char *mysql_server;
|
||||||
|
const char *mysql_user;
|
||||||
|
const char *mysql_password;
|
||||||
|
const char *mysql_database;
|
||||||
|
|
||||||
unsigned int token_id_length;
|
unsigned int token_id_length;
|
||||||
enum key_mode mode;
|
enum key_mode mode;
|
||||||
const char *chalresp_path;
|
const char *chalresp_path;
|
||||||
@ -164,8 +169,19 @@ authorize_user_token (struct cfg *cfg,
|
|||||||
pam_handle_t *pamh)
|
pam_handle_t *pamh)
|
||||||
{
|
{
|
||||||
int retval = AUTH_ERROR;
|
int retval = AUTH_ERROR;
|
||||||
|
if (cfg->mysql_server)
|
||||||
if (cfg->auth_file)
|
{
|
||||||
|
#ifdef HAVE_MYSQL
|
||||||
|
/* Administrator had configured the database and specified is name
|
||||||
|
as an argument for this module.
|
||||||
|
*/
|
||||||
|
DBG ("Using Mariadb or Mysql Database");
|
||||||
|
retval = check_user_token_mysql(cfg->mysql_server, cfg->mysql_user, cfg->mysql_password, cfg->mysql_database, username, otp_id, cfg->debug, cfg->debug_file);
|
||||||
|
#else
|
||||||
|
DBG (("Trying to use MYSQL, but this function is not compiled in pam_yubico!!"));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (cfg->auth_file)
|
||||||
{
|
{
|
||||||
/* Administrator had configured the file and specified is name
|
/* Administrator had configured the file and specified is name
|
||||||
as an argument for this module.
|
as an argument for this module.
|
||||||
@ -874,6 +890,15 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
|
|||||||
cfg->mode = CLIENT;
|
cfg->mode = CLIENT;
|
||||||
if (strncmp (argv[i], "chalresp_path=", 14) == 0)
|
if (strncmp (argv[i], "chalresp_path=", 14) == 0)
|
||||||
cfg->chalresp_path = argv[i] + 14;
|
cfg->chalresp_path = argv[i] + 14;
|
||||||
|
if (strncmp (argv[i], "mysql_server=", 13) == 0)
|
||||||
|
cfg->mysql_server = argv[i] + 13;
|
||||||
|
if (strncmp (argv[i], "mysql_user=", 11) == 0)
|
||||||
|
cfg->mysql_user = argv[i] + 11;
|
||||||
|
if (strncmp (argv[i], "mysql_password=", 15) == 0)
|
||||||
|
cfg->mysql_password = argv[i] + 15;
|
||||||
|
if (strncmp (argv[i], "mysql_database=", 15) == 0)
|
||||||
|
cfg->mysql_database = argv[i] + 15;
|
||||||
|
|
||||||
if (strncmp (argv[i], "debug_file=", 11) == 0)
|
if (strncmp (argv[i], "debug_file=", 11) == 0)
|
||||||
{
|
{
|
||||||
const char *filename = argv[i] + 11;
|
const char *filename = argv[i] + 11;
|
||||||
@ -939,6 +964,9 @@ parse_cfg (int flags, int argc, const char **argv, struct cfg *cfg)
|
|||||||
DBG ("token_id_length=%u", cfg->token_id_length);
|
DBG ("token_id_length=%u", cfg->token_id_length);
|
||||||
DBG ("mode=%s", cfg->mode == CLIENT ? "client" : "chresp" );
|
DBG ("mode=%s", cfg->mode == CLIENT ? "client" : "chresp" );
|
||||||
DBG ("chalresp_path=%s", cfg->chalresp_path ? cfg->chalresp_path : "(null)");
|
DBG ("chalresp_path=%s", cfg->chalresp_path ? cfg->chalresp_path : "(null)");
|
||||||
|
DBG ("mysql_server=%s", cfg->mysql_server ? cfg->mysql_server : "(null)");
|
||||||
|
DBG ("mysql_user=%s", cfg->mysql_user ? cfg->mysql_user : "(null)");
|
||||||
|
DBG ("mysql_database=%s", cfg->mysql_database ? cfg->mysql_database : "(null)");
|
||||||
|
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
close(fd);
|
close(fd);
|
||||||
|
@ -7,7 +7,7 @@ autoreconf -i
|
|||||||
if [ "x$TRAVIS_OS_NAME" != "xosx" ]; then
|
if [ "x$TRAVIS_OS_NAME" != "xosx" ]; then
|
||||||
sudo add-apt-repository -y ppa:yubico/stable
|
sudo add-apt-repository -y ppa:yubico/stable
|
||||||
sudo apt-get update -qq || true
|
sudo apt-get update -qq || true
|
||||||
sudo apt-get install -qq -y --no-install-recommends libykclient-dev libpam0g-dev libyubikey-dev asciidoc docbook-xsl xsltproc libxml2-utils $EXTRA
|
sudo apt-get install -qq -y --no-install-recommends libykclient-dev libpam0g-dev libyubikey-dev asciidoc docbook-xsl xsltproc libxml2-utils libmysqlclient-dev $EXTRA
|
||||||
else
|
else
|
||||||
brew update
|
brew update
|
||||||
brew install pkg-config
|
brew install pkg-config
|
||||||
@ -17,6 +17,7 @@ else
|
|||||||
brew install libyubikey
|
brew install libyubikey
|
||||||
brew install ykclient
|
brew install ykclient
|
||||||
brew install ykpers
|
brew install ykpers
|
||||||
|
brew install mysql-connector-c #Mysql
|
||||||
cpanp install Net::LDAP::Server
|
cpanp install Net::LDAP::Server
|
||||||
|
|
||||||
# this is required so asciidoc can find the xml catalog
|
# this is required so asciidoc can find the xml catalog
|
||||||
|
193
util.c
193
util.c
@ -52,6 +52,10 @@
|
|||||||
#include <ykdef.h>
|
#include <ykdef.h>
|
||||||
#endif /* HAVE_CR */
|
#endif /* HAVE_CR */
|
||||||
|
|
||||||
|
#ifdef HAVE_MYSQL
|
||||||
|
#include <mysql.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
int
|
int
|
||||||
get_user_cfgfile_path(const char *common_path, const char *filename, const struct passwd *user, char **fn)
|
get_user_cfgfile_path(const char *common_path, const char *filename, const struct passwd *user, char **fn)
|
||||||
{
|
{
|
||||||
@ -93,6 +97,195 @@ get_user_cfgfile_path(const char *common_path, const char *filename, const struc
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_MYSQL
|
||||||
|
/*
|
||||||
|
* This function will look for users name with valid user token id, in a database Mysql
|
||||||
|
*
|
||||||
|
* Returns one of AUTH_FOUND, AUTH_NOT_FOUND, AUTH_NO_TOKENS, AUTH_ERROR.
|
||||||
|
*
|
||||||
|
* Need database with this table structure:
|
||||||
|
*
|
||||||
|
* CREATE TABLE IF NOT EXISTS `otp`.`yubikey_mappings`(
|
||||||
|
* `otp_id` VARCHAR(12) NOT NULL ,
|
||||||
|
* `username` VARCHAR(64) NOT NULL ,
|
||||||
|
* PRIMARY KEY (`otp_id`(12))
|
||||||
|
* );
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
check_user_token_mysql(const char *mysql_server,
|
||||||
|
const char *mysql_user,
|
||||||
|
const char *mysql_password,
|
||||||
|
const char *mysql_database,
|
||||||
|
const char *username,
|
||||||
|
const char *otp_id,
|
||||||
|
int verbose,
|
||||||
|
FILE *debug_file)
|
||||||
|
{
|
||||||
|
|
||||||
|
int retval = AUTH_ERROR;
|
||||||
|
int fd;
|
||||||
|
struct stat st;
|
||||||
|
FILE *opwfile;
|
||||||
|
MYSQL *con = NULL;
|
||||||
|
MYSQL_STMT *stmt;
|
||||||
|
MYSQL_BIND ps_params[2];
|
||||||
|
MYSQL_BIND bind[1];
|
||||||
|
long unsigned int str_username;
|
||||||
|
long unsigned int str_otp;
|
||||||
|
long unsigned int length;
|
||||||
|
int int_data;
|
||||||
|
int row_count;
|
||||||
|
bool is_null;
|
||||||
|
bool error;
|
||||||
|
|
||||||
|
if(mysql_library_init(0, NULL, NULL)){
|
||||||
|
if(verbose){
|
||||||
|
D (debug_file, "could not initialize MySQL client library");
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
con = mysql_init(con);
|
||||||
|
if(!con) {
|
||||||
|
if(verbose)
|
||||||
|
D (debug_file, "out of memorys");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mysql_real_connect(con, mysql_server,mysql_user,mysql_password,mysql_database, 0, NULL, 0) == NULL)
|
||||||
|
{
|
||||||
|
if(verbose)
|
||||||
|
D (debug_file, "Connection failed ...");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
stmt = mysql_stmt_init(con);
|
||||||
|
if(!stmt)
|
||||||
|
{
|
||||||
|
if(verbose)
|
||||||
|
D (debug_file, "Connection failed ... 2");
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *sql = "SELECT count(username) FROM yubikey_mappings WHERE username = ?;";
|
||||||
|
const char *sql2 = "SELECT count(username) FROM yubikey_mappings WHERE username = ? and otp_id = ?;";
|
||||||
|
|
||||||
|
if(otp_id == NULL)
|
||||||
|
{
|
||||||
|
if(mysql_stmt_prepare(stmt, sql, strlen(sql)))
|
||||||
|
{
|
||||||
|
if(verbose)
|
||||||
|
D (debug_file, "mysql_stmt_prepare() failed %s", mysql_stmt_error(stmt));
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(mysql_stmt_prepare(stmt, sql2, strlen(sql2)))
|
||||||
|
{
|
||||||
|
if(verbose)
|
||||||
|
D (debug_file, "mysql_stmt_prepare() failed %s", mysql_stmt_error(stmt));
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
str_username = strlen(username);
|
||||||
|
memset(ps_params, 0, sizeof(ps_params));
|
||||||
|
ps_params[0].buffer_type = MYSQL_TYPE_STRING;
|
||||||
|
ps_params[0].buffer = (char *)username;
|
||||||
|
ps_params[0].buffer_length = str_username;
|
||||||
|
ps_params[0].length = &str_username;
|
||||||
|
ps_params[0].is_null = 0;
|
||||||
|
|
||||||
|
if(otp_id != NULL)
|
||||||
|
{
|
||||||
|
str_otp= strlen(otp_id);
|
||||||
|
ps_params[1].buffer_type = MYSQL_TYPE_STRING;
|
||||||
|
ps_params[1].buffer = (char *)otp_id;
|
||||||
|
ps_params[1].buffer_length = str_otp;
|
||||||
|
ps_params[1].length = &str_otp;
|
||||||
|
ps_params[1].is_null = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mysql_stmt_bind_param(stmt, ps_params))
|
||||||
|
{
|
||||||
|
if(verbose)
|
||||||
|
D (debug_file, "mysql_stmt_bind_param() failed %s", mysql_stmt_error(stmt));
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mysql_stmt_execute(stmt))
|
||||||
|
{
|
||||||
|
if(verbose)
|
||||||
|
D (debug_file, "mysql_stmt_execute() failed %s", mysql_stmt_error(stmt));
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(bind, 0, sizeof(bind));
|
||||||
|
bind[0].buffer_type = MYSQL_TYPE_LONG;
|
||||||
|
bind[0].buffer = (char *)&int_data;
|
||||||
|
bind[0].length = &length;
|
||||||
|
bind[0].is_null = &is_null;
|
||||||
|
bind[0].error = &error;
|
||||||
|
|
||||||
|
if(mysql_stmt_bind_result(stmt, bind))
|
||||||
|
{
|
||||||
|
if(verbose)
|
||||||
|
D (debug_file, "mysql_stmt_bind_result() failed %s", mysql_stmt_error(stmt));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mysql_stmt_store_result(stmt))
|
||||||
|
{
|
||||||
|
if(verbose)
|
||||||
|
D (debug_file, "mysql_stmt_store_result() failed %s", mysql_stmt_error(stmt));
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(!mysql_stmt_fetch(stmt))
|
||||||
|
{
|
||||||
|
if(is_null)
|
||||||
|
{
|
||||||
|
D (debug_file, "mysql_stmt_fetch() failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(otp_id != NULL){
|
||||||
|
if(int_data)
|
||||||
|
{
|
||||||
|
return AUTH_FOUND;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return AUTH_NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(otp_id == NULL)
|
||||||
|
{
|
||||||
|
if(int_data)
|
||||||
|
{
|
||||||
|
return AUTH_NOT_FOUND;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return AUTH_NO_TOKENS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mysql_stmt_close(stmt))
|
||||||
|
{
|
||||||
|
if(verbose)
|
||||||
|
D (debug_file, "mysql_stmt_close() failed %s", mysql_stmt_error(stmt));
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
mysql_close(con);
|
||||||
|
mysql_library_end();
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function will look for users name with valid user token id.
|
* This function will look for users name with valid user token id.
|
||||||
|
3
util.h
3
util.h
@ -51,6 +51,9 @@
|
|||||||
#define AUTH_NOT_FOUND -1 /* The requested token is not associated to the user */
|
#define AUTH_NOT_FOUND -1 /* The requested token is not associated to the user */
|
||||||
|
|
||||||
int get_user_cfgfile_path(const char *common_path, const char *filename, const struct passwd *user, char **fn);
|
int get_user_cfgfile_path(const char *common_path, const char *filename, const struct passwd *user, char **fn);
|
||||||
|
#ifdef HAVE_MYSQL
|
||||||
|
int check_user_token_mysql(const char *mysql_server,const char *mysql_user,const char *mysql_password,const char *mysql_database,const char *username,const char *otp_id,int verbose,FILE *debug_file);
|
||||||
|
#endif
|
||||||
int check_user_token(const char *authfile, const char *username, const char *otp_id, int verbose, FILE *debug_file);
|
int check_user_token(const char *authfile, const char *username, const char *otp_id, int verbose, FILE *debug_file);
|
||||||
|
|
||||||
#if HAVE_CR
|
#if HAVE_CR
|
||||||
|
Loading…
x
Reference in New Issue
Block a user