Several of changes involving PSK checks.
This commit is contained in:
parent
fab0936a72
commit
9fdacb611f
3 changed files with 186 additions and 34 deletions
|
@ -1,7 +1,7 @@
|
||||||
CFLAGS += -fPIC -Wall
|
CFLAGS += -fPIC -Wall
|
||||||
|
|
||||||
ifdef DEBUG
|
ifdef DEBUG
|
||||||
CFLAGS += -O0 -ggdb -DDEBUG
|
CFLAGS += -O0 -ggdb
|
||||||
else
|
else
|
||||||
CFLAGS += -O2
|
CFLAGS += -O2
|
||||||
endif
|
endif
|
||||||
|
@ -24,6 +24,8 @@ endif
|
||||||
|
|
||||||
all: ${obj}
|
all: ${obj}
|
||||||
|
|
||||||
|
debug:
|
||||||
|
${MAKE} DEBUG=1 all
|
||||||
|
|
||||||
${obj}: ${objo}
|
${obj}: ${objo}
|
||||||
${CC} ${LDFLAGS} -o ${obj} ${objo}
|
${CC} ${LDFLAGS} -o ${obj} ${objo}
|
||||||
|
|
|
@ -2,16 +2,47 @@
|
||||||
* pam_url - authenticate against webservers
|
* pam_url - authenticate against webservers
|
||||||
*
|
*
|
||||||
* This software is opensource software licensed under the GNU Public License version 2.
|
* This software is opensource software licensed under the GNU Public License version 2.
|
||||||
* The author of this software is Sascha Thomas Spreitzer <sspreitzer@fedoraproject.org>.
|
* The author of this software is Sascha Thomas Spreitzer <sspreitzer (at) fedoraproject.org>.
|
||||||
* Please take a look in the COPYING, INSTALL and README files.
|
* Please take a look in the COPYING, INSTALL and README files.
|
||||||
*
|
*
|
||||||
* USE THIS SOFTWARE WITH ABSOLUTELY NO GUARANTEE AND WARRANTY
|
* USE THIS SOFTWARE WITH ABSOLUTELY NO GUARANTEE AND WARRANTY
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* /etc/pam.d/sshd or /etc/pam.d/system-auth:
|
||||||
|
*
|
||||||
|
* [...]
|
||||||
|
* auth sufficient pam_url.so https://www.example.org/ secret user passwd &do=login
|
||||||
|
* auth sufficient pam_url.so URL PSK USER PASSWD EXTRA
|
||||||
|
* [...]
|
||||||
|
* This module takes 4 arguments:
|
||||||
|
* - URL = HTTPS URL
|
||||||
|
* - PSK = Pre Shared Key
|
||||||
|
* - USER = The name of the user variable
|
||||||
|
* - PASSWD = The name of the password variable
|
||||||
|
* - EXTRA = additional url encoded data
|
||||||
|
*
|
||||||
|
* auth sufficient pam_url.so https://www.example.org/ secret user passwd &do=auth
|
||||||
|
* This line forms the following url encoded POST data:
|
||||||
|
* ?user=<username>&passwd=<pass>&mode=<PAM_AUTH|PAM_ACCT|PAM_SESS|PAM_PASS>&PSK=secret&do=auth
|
||||||
|
* It should return either 200 OK with PSK in the body or 403 Forbidden if unsuccessful.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PAM_SM_AUTH
|
#ifndef NAME
|
||||||
#define PAM_SM_ACCOUNT
|
#define NAME "pam_url"
|
||||||
#define PAM_SM_SESSION
|
#endif
|
||||||
#define PAM_SM_PASSWORD
|
|
||||||
|
#ifndef VERS
|
||||||
|
#define VERS "0.0"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef USER_AGENT
|
||||||
|
#define USER_AGENT NAME "/" VERS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PAM_SM_AUTH 1
|
||||||
|
#define PAM_SM_ACCOUNT 2
|
||||||
|
#define PAM_SM_SESSION 3
|
||||||
|
#define PAM_SM_PASSWORD 4
|
||||||
|
|
||||||
#include <security/pam_modules.h>
|
#include <security/pam_modules.h>
|
||||||
#include <security/pam_ext.h>
|
#include <security/pam_ext.h>
|
||||||
|
@ -28,21 +59,16 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <unistd.h>
|
||||||
// /etc/pam.d/sshd or /etc/pam.d/system-auth:
|
|
||||||
//
|
|
||||||
// [...]
|
|
||||||
// auth sufficient pam_url.so https://www.example.org/ user passwd &mode=login
|
|
||||||
// auth sufficient pam_url.so URL USER PASSWD EXTRA
|
|
||||||
// [...]
|
|
||||||
// This module takes 3 arguments:
|
|
||||||
// URL, USERNAME, PASSWORD
|
|
||||||
// The username ,password and extra fields are optional.
|
|
||||||
|
|
||||||
#ifndef DEF_URL
|
#ifndef DEF_URL
|
||||||
#define DEF_URL "https://www.example.org/"
|
#define DEF_URL "https://www.example.org/"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef DEF_PSK
|
||||||
|
#define DEF_PSK "presharedsecret"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef DEF_USER
|
#ifndef DEF_USER
|
||||||
#define DEF_USER "user"
|
#define DEF_USER "user"
|
||||||
#endif
|
#endif
|
||||||
|
@ -52,17 +78,22 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef DEF_EXTRA
|
#ifndef DEF_EXTRA
|
||||||
#define DEF_EXTRA "&mode=login"
|
#define DEF_EXTRA "&do=pam_url"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct pam_url_opts_ {
|
typedef struct pam_url_opts_ {
|
||||||
char* url;
|
char* url;
|
||||||
|
char* PSK;
|
||||||
char* userfield;
|
char* userfield;
|
||||||
char* passwdfield;
|
char* passwdfield;
|
||||||
char* extrafield;
|
char* extrafield;
|
||||||
|
char* mode;
|
||||||
|
|
||||||
const void* user;
|
const void* user;
|
||||||
const void* passwd;
|
const void* passwd;
|
||||||
|
|
||||||
|
FILE* answer;
|
||||||
|
char* fanswer;
|
||||||
} pam_url_opts;
|
} pam_url_opts;
|
||||||
|
|
||||||
void notice(pam_handle_t* pamh, const char *msg)
|
void notice(pam_handle_t* pamh, const char *msg)
|
||||||
|
@ -72,9 +103,7 @@ void notice(pam_handle_t* pamh, const char *msg)
|
||||||
|
|
||||||
void debug(pam_handle_t* pamh, const char *msg)
|
void debug(pam_handle_t* pamh, const char *msg)
|
||||||
{
|
{
|
||||||
// #ifdef DEBUG
|
pam_syslog(pamh, LOG_ERR, "%s", msg);
|
||||||
pam_syslog(pamh, LOG_NOTICE, "%s", msg);
|
|
||||||
// #endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_password(pam_handle_t* pamh, pam_url_opts* opts)
|
int get_password(pam_handle_t* pamh, pam_url_opts* opts)
|
||||||
|
@ -93,11 +122,14 @@ int get_password(pam_handle_t* pamh, pam_url_opts* opts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_opts(pam_url_opts* opts, int argc, const char** argv)
|
int parse_opts(pam_url_opts* opts, int argc, const char** argv, int mode)
|
||||||
{
|
{
|
||||||
opts->url = calloc(1, strlen(DEF_URL) + 1);
|
opts->url = calloc(1, strlen(DEF_URL) + 1);
|
||||||
strcpy(opts->url, DEF_URL);
|
strcpy(opts->url, DEF_URL);
|
||||||
|
|
||||||
|
opts->PSK = calloc(1, strlen(DEF_PSK) + 1);
|
||||||
|
strcpy(opts->PSK, DEF_PSK);
|
||||||
|
|
||||||
opts->userfield = calloc(1, strlen(DEF_USER) + 1);
|
opts->userfield = calloc(1, strlen(DEF_USER) + 1);
|
||||||
strcpy(opts->userfield, DEF_USER);
|
strcpy(opts->userfield, DEF_USER);
|
||||||
|
|
||||||
|
@ -118,22 +150,59 @@ int parse_opts(pam_url_opts* opts, int argc, const char** argv)
|
||||||
strcpy(opts->url, argv[0]);
|
strcpy(opts->url, argv[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( argc >= 2)
|
if( argc >= 2 )
|
||||||
{
|
{
|
||||||
opts->userfield = calloc(1, strlen(argv[1]) + 1);
|
opts->PSK = calloc(1, strlen(argv[1]) +1);
|
||||||
strcpy(opts->userfield, argv[1]);
|
strcpy(opts->PSK, argv[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( argc >= 3)
|
if( argc >= 3 )
|
||||||
{
|
{
|
||||||
opts->passwdfield = calloc(1, strlen(argv[2]) + 1);
|
opts->userfield = calloc(1, strlen(argv[2]) + 1);
|
||||||
strcpy(opts->passwdfield, argv[2]);
|
strcpy(opts->userfield, argv[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( argc >= 4 )
|
if( argc >= 4 )
|
||||||
{
|
{
|
||||||
opts->extrafield = calloc(1, strlen(argv[3]) + 1);
|
opts->passwdfield = calloc(1, strlen(argv[3]) + 1);
|
||||||
strcpy(opts->extrafield, argv[3]);
|
strcpy(opts->passwdfield, argv[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( argc >= 5 )
|
||||||
|
{
|
||||||
|
opts->extrafield = calloc(1, strlen(argv[4]) + 1);
|
||||||
|
strcpy(opts->extrafield, argv[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
opts->fanswer = calloc(1, strlen(tmpnam(NULL)) + 1 );
|
||||||
|
strcpy(opts->fanswer, tmpnam(NULL));
|
||||||
|
|
||||||
|
switch(mode)
|
||||||
|
{
|
||||||
|
case PAM_SM_ACCOUNT:
|
||||||
|
opts->mode = calloc(1, strlen("PAM_SM_ACCOUNT") + 1);
|
||||||
|
strcpy(opts->mode, "PAM_SM_ACCOUNT");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAM_SM_SESSION:
|
||||||
|
opts->mode = calloc(1, strlen("PAM_SM_SESSION") + 1);
|
||||||
|
strcpy(opts->mode, "PAM_SM_SESSION");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PAM_SM_PASSWORD:
|
||||||
|
opts->mode = calloc(1, strlen("PAM_SM_PASSWORD") + 1);
|
||||||
|
strcpy(opts->mode, "PAM_SM_PASSWORD");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // PAM_SM_AUTH
|
||||||
|
opts->mode = calloc(1, strlen("PAM_SM_AUTH") + 1);
|
||||||
|
strcpy(opts->mode,"PAM_SM_AUTH");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( NULL == (opts->answer = fopen(opts->fanswer, "w+")) )
|
||||||
|
{
|
||||||
|
return PAM_AUTH_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return PAM_SUCCESS;
|
return PAM_SUCCESS;
|
||||||
|
@ -144,13 +213,29 @@ int fetch_url(pam_url_opts opts)
|
||||||
CURL* eh = NULL;
|
CURL* eh = NULL;
|
||||||
char* post = NULL;
|
char* post = NULL;
|
||||||
|
|
||||||
post = calloc(1, strlen(opts.userfield) +
|
post = calloc(1,
|
||||||
|
strlen("PSK=") +
|
||||||
|
strlen(opts.PSK) +
|
||||||
|
strlen("&") +
|
||||||
|
strlen(opts.userfield) +
|
||||||
|
strlen("=") +
|
||||||
strlen(opts.user) +
|
strlen(opts.user) +
|
||||||
|
strlen("&") +
|
||||||
strlen(opts.passwdfield) +
|
strlen(opts.passwdfield) +
|
||||||
|
strlen("=") +
|
||||||
strlen(opts.passwd) +
|
strlen(opts.passwd) +
|
||||||
strlen(opts.extrafield) + 4); // 4 = two times "=" and one "&" and \0
|
strlen("&mode=") +
|
||||||
|
strlen(opts.mode) +
|
||||||
|
strlen(opts.extrafield) +
|
||||||
|
strlen("\0") );
|
||||||
|
|
||||||
sprintf(post, "%s=%s&%s=%s%s", opts.userfield, (char*)opts.user, opts.passwdfield, (char*)opts.passwd, opts.extrafield);
|
sprintf(post, "PSK=%s&%s=%s&%s=%s&mode=%s%s", opts.PSK,
|
||||||
|
opts.userfield,
|
||||||
|
(char*)opts.user,
|
||||||
|
opts.passwdfield,
|
||||||
|
(char*)opts.passwd,
|
||||||
|
opts.mode,
|
||||||
|
opts.extrafield);
|
||||||
|
|
||||||
if( 0 != curl_global_init(CURL_GLOBAL_ALL) )
|
if( 0 != curl_global_init(CURL_GLOBAL_ALL) )
|
||||||
return PAM_AUTH_ERR;
|
return PAM_AUTH_ERR;
|
||||||
|
@ -164,6 +249,18 @@ int fetch_url(pam_url_opts opts)
|
||||||
return PAM_AUTH_ERR;
|
return PAM_AUTH_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( CURLE_OK != curl_easy_setopt(eh, CURLOPT_USERAGENT, USER_AGENT) )
|
||||||
|
{
|
||||||
|
curl_easy_cleanup(eh);
|
||||||
|
return PAM_AUTH_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( CURLE_OK != curl_easy_setopt(eh, CURLOPT_WRITEDATA, opts.answer) )
|
||||||
|
{
|
||||||
|
curl_easy_cleanup(eh);
|
||||||
|
return PAM_AUTH_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
if( CURLE_OK != curl_easy_setopt(eh, CURLOPT_URL, opts.url) )
|
if( CURLE_OK != curl_easy_setopt(eh, CURLOPT_URL, opts.url) )
|
||||||
{
|
{
|
||||||
curl_easy_cleanup(eh);
|
curl_easy_cleanup(eh);
|
||||||
|
@ -200,6 +297,51 @@ int fetch_url(pam_url_opts opts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int check_psk(pam_url_opts opts)
|
||||||
|
{
|
||||||
|
int ret=0;
|
||||||
|
char* buf;
|
||||||
|
|
||||||
|
if( 0 != access( opts.fanswer, R_OK|W_OK ) || NULL == opts.answer )
|
||||||
|
{
|
||||||
|
ret++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind(opts.answer);
|
||||||
|
|
||||||
|
// buf = calloc(1, 2000);
|
||||||
|
|
||||||
|
if( NULL == fgets(buf, sizeof(buf),opts.answer) )
|
||||||
|
{
|
||||||
|
ret++;
|
||||||
|
rewind(opts.answer);
|
||||||
|
return PAM_AUTH_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( 0 != strncmp(buf, opts.PSK, strlen(opts.PSK)) )
|
||||||
|
{
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind(opts.answer);
|
||||||
|
|
||||||
|
if( 0 != ret )
|
||||||
|
{
|
||||||
|
return PAM_AUTH_ERR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cleanup(pam_url_opts opts)
|
||||||
|
{
|
||||||
|
fclose(opts.answer);
|
||||||
|
remove(opts.fanswer);
|
||||||
|
}
|
||||||
|
|
||||||
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
PAM_EXTERN int pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
|
||||||
{ // by now, a dummy
|
{ // by now, a dummy
|
||||||
return PAM_SUCCESS;
|
return PAM_SUCCESS;
|
||||||
|
@ -234,7 +376,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( PAM_SUCCESS != parse_opts(&opts, argc, argv) )
|
if( PAM_SUCCESS != parse_opts(&opts, argc, argv, PAM_SM_AUTH) )
|
||||||
{
|
{
|
||||||
ret++;
|
ret++;
|
||||||
debug(pamh, "Could not parse module options.");
|
debug(pamh, "Could not parse module options.");
|
||||||
|
@ -246,10 +388,18 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags,
|
||||||
debug(pamh, "Could not fetch URL.");
|
debug(pamh, "Could not fetch URL.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( PAM_SUCCESS != check_psk(opts) )
|
||||||
|
{
|
||||||
|
ret++;
|
||||||
|
debug(pamh, "Pre Shared Key differs from ours.");
|
||||||
|
}
|
||||||
|
|
||||||
if( 0 == ret )
|
if( 0 == ret )
|
||||||
return PAM_SUCCESS;
|
return PAM_SUCCESS;
|
||||||
|
|
||||||
debug(pamh, "Authentication failed.");
|
debug(pamh, "Authentication failed.");
|
||||||
|
cleanup(opts);
|
||||||
|
|
||||||
return PAM_AUTH_ERR;
|
return PAM_AUTH_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ PAM module to fetch from URL.
|
||||||
%setup -n %{name}
|
%setup -n %{name}
|
||||||
|
|
||||||
%build
|
%build
|
||||||
make DESTDIR=%{buildroot} all
|
make DEBUG=1 DESTDIR=%{buildroot} all
|
||||||
|
|
||||||
%install
|
%install
|
||||||
make DESTDIR=%{buildroot} install
|
make DESTDIR=%{buildroot} install
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue