mirror of
https://github.com/Yubico/yubico-pam.git
synced 2024-11-29 00:24:11 +01:00
Add support of Mysql/Mariadb for the yubikey_mapping
Add support of Mysql/Mariadb for the yubikey_mapping Mise à jour sql complete, manque la documentation Final clean Add packages dependency actions: apt update Fix bool variable cause error build travis Fix job #2 Fix job #3 Fix #4 fix &null fix &null fix &null Fix line 257 %s test Apple integration test Apple integration Timeout Travis extend Timeout travis extend Fix klali comment Fix warning fix configure.ac fix configure.ac Update configure.ac Update util.c Update util.h Update util.c Update util.c Update util.c Update util.c Fix white space fix left column
This commit is contained in:
parent
07892d21e0
commit
b708e6dcf1
3
.github/workflows/codeql-analysis.yml
vendored
3
.github/workflows/codeql-analysis.yml
vendored
@ -30,8 +30,9 @@ jobs:
|
||||
|
||||
- name: Build yubico-pam
|
||||
run: |
|
||||
sudo apt update
|
||||
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
|
||||
./configure
|
||||
make
|
||||
|
2
.github/workflows/scan.yml
vendored
2
.github/workflows/scan.yml
vendored
@ -8,7 +8,7 @@ on:
|
||||
env:
|
||||
SCAN_IMG:
|
||||
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:
|
||||
build:
|
||||
|
14
.travis.yml
14
.travis.yml
@ -1,4 +1,3 @@
|
||||
sudo: required
|
||||
language: c
|
||||
os:
|
||||
- linux
|
||||
@ -7,13 +6,14 @@ compiler:
|
||||
- gcc
|
||||
- clang
|
||||
env:
|
||||
- CONFIGURE_ARGS="" EXTRA="libldap2-dev libykpers-1-dev libnet-ldap-server-perl"
|
||||
- CONFIGURE_ARGS="--without-ldap" EXTRA="libykpers-1-dev"
|
||||
- CONFIGURE_ARGS="--without-cr" EXTRA="libldap2-dev libnet-ldap-server-perl"
|
||||
- CONFIGURE_ARGS="--without-ldap --without-cr"
|
||||
- CONFIGURE_ARGS="" EXTRA="libldap2-dev libykpers-1-dev libnet-ldap-server-perl libmysqlclient-dev"
|
||||
- CONFIGURE_ARGS="--without-ldap" EXTRA="libykpers-1-dev libmysqlclient-dev"
|
||||
- CONFIGURE_ARGS="--without-cr" EXTRA="libldap2-dev libnet-ldap-server-perl libmysqlclient-dev"
|
||||
- CONFIGURE_ARGS="--without-ldap --without-cr" EXTRA="libmysqlclient-dev"
|
||||
script: tests/aux/build-and-test.sh
|
||||
matrix:
|
||||
jobs:
|
||||
install: travis_wait 30 mvn install
|
||||
include:
|
||||
- compiler: gcc
|
||||
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
|
||||
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
|
||||
|
||||
|
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)])],
|
||||
[])])
|
||||
|
||||
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>],
|
||||
[ykclient_set_proxy(0, 0)])
|
||||
|
@ -116,6 +116,18 @@ CA certitificate file for the LDAP connection.
|
||||
*chalresp_path*=_path_::
|
||||
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
|
||||
|
||||
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 *yubi_attr;
|
||||
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;
|
||||
enum key_mode mode;
|
||||
const char *chalresp_path;
|
||||
@ -164,8 +169,19 @@ authorize_user_token (struct cfg *cfg,
|
||||
pam_handle_t *pamh)
|
||||
{
|
||||
int retval = AUTH_ERROR;
|
||||
|
||||
if (cfg->auth_file)
|
||||
if (cfg->mysql_server)
|
||||
{
|
||||
#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
|
||||
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;
|
||||
if (strncmp (argv[i], "chalresp_path=", 14) == 0)
|
||||
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)
|
||||
{
|
||||
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 ("mode=%s", cfg->mode == CLIENT ? "client" : "chresp" );
|
||||
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)
|
||||
close(fd);
|
||||
|
@ -7,7 +7,7 @@ autoreconf -i
|
||||
if [ "x$TRAVIS_OS_NAME" != "xosx" ]; then
|
||||
sudo add-apt-repository -y ppa:yubico/stable
|
||||
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
|
||||
brew update
|
||||
brew install pkg-config
|
||||
@ -17,6 +17,7 @@ else
|
||||
brew install libyubikey
|
||||
brew install ykclient
|
||||
brew install ykpers
|
||||
brew install mysql-connector-c #Mysql
|
||||
cpanp install Net::LDAP::Server
|
||||
|
||||
# this is required so asciidoc can find the xml catalog
|
||||
|
193
util.c
193
util.c
@ -52,6 +52,10 @@
|
||||
#include <ykdef.h>
|
||||
#endif /* HAVE_CR */
|
||||
|
||||
#ifdef HAVE_MYSQL
|
||||
#include <mysql.h>
|
||||
#endif
|
||||
|
||||
int
|
||||
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;
|
||||
}
|
||||
|
||||
#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.
|
||||
|
3
util.h
3
util.h
@ -51,6 +51,9 @@
|
||||
#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);
|
||||
#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);
|
||||
|
||||
#if HAVE_CR
|
||||
|
Loading…
Reference in New Issue
Block a user