diff --git a/examples/pam_url.conf b/examples/pam_url.conf index 3ff0c09..e53fab9 100644 --- a/examples/pam_url.conf +++ b/examples/pam_url.conf @@ -5,16 +5,19 @@ pam_url: settings: { uri = "https://127.0.0.1/pam_auth/"; # URI to fetch - presharedkey = "rabbit"; # Presharedkey to send to server within data + returncode = "OK"; # The remote script/cgi should return a 200 http code and this string as its only results userfield = "user"; # userfield name to send passwdfield = "pass"; # passwdfield name to send extradata = "&do=login"; # extradata to send + prompt = "Password: "; # password prompt }; ssl: { verify_peer = false; # Should we verify SSL ? verify_host = true; # Should we verify the CN in the SSL cert? + client_cert = "/etc/pki/pam_url_cert.pem"; # file to use as client-side certificate + client_key = "/etc/pki/pam_url_key.pem"; # file to use as client-side key (can be same file as above if a single cert) }; }; diff --git a/pam_url.c b/pam_url.c index 6c43ff0..253876f 100644 --- a/pam_url.c +++ b/pam_url.c @@ -13,9 +13,22 @@ void debug(pam_handle_t* pamh, const char *msg) int get_password(pam_handle_t* pamh, pam_url_opts* opts) { char* p = NULL; - pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &p, "%s", "Password: "); - if( NULL != p ) + int i = 0; + + config_t config; + config_init(&config); + config_read_file(&config,"/etc/pam_url.conf"); + + char* prompt; + if( CONFIG_FALSE == config_lookup_string(&config, "pam_url.settings.prompt", &prompt) ) + { + prompt = calloc(1, strlen(DEF_PROMPT) + 1); + strcpy(prompt, DEF_PROMPT); + } + + pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &p, "%s", prompt); + if( NULL != p && strlen(p) > 0) { opts->passwd = p; return PAM_SUCCESS; @@ -38,14 +51,14 @@ int parse_opts(pam_url_opts* opts, int argc, const char** argv, int mode) if( 0 != argc && NULL != argv) { - for( i = 0; i <= argc; i++) + for( i = 0; i < argc; i++) { if( 0 == strcmp(argv[i], "debug") ) { pam_url_debug = 1; } - if( 0 == strncmp(argv[i], "config=", strlen("config=")) ) + else if( 0 == strncmp(argv[i], "config=", strlen("config=")) ) { opts->configfile = calloc(1, strlen(argv[i]) - strlen("config=") + 1 ); strcpy(opts->configfile, argv[i] + strlen("config=") ); @@ -85,10 +98,10 @@ int parse_opts(pam_url_opts* opts, int argc, const char** argv, int mode) strcpy(opts->url, DEF_URL); } - if( CONFIG_FALSE == config_lookup_string(&config, "pam_url.settings.presharedkey", &opts->PSK) ) + if( CONFIG_FALSE == config_lookup_string(&config, "pam_url.settings.returncode", &opts->RC) ) { - opts->PSK = calloc(1, strlen(DEF_PSK) + 1); - strcpy(opts->PSK, DEF_PSK); + opts->RC = calloc(1, strlen(DEF_RETURNCODE) + 1); + strcpy(opts->RC, DEF_RETURNCODE); } if( CONFIG_FALSE == config_lookup_string(&config, "pam_url.settings.userfield", &opts->userfield) ) @@ -119,6 +132,20 @@ int parse_opts(pam_url_opts* opts, int argc, const char** argv, int mode) opts->ssl_verify_host = 1; } + if( CONFIG_FALSE == config_lookup_string(&config, "pam_url.ssl.client_cert", &opts->sslcert) ) + { + opts->sslcert = calloc(1, strlen(DEF_SSLCERT) + 1); + strcpy(opts->sslcert, DEF_SSLCERT); + } + + + if( CONFIG_FALSE == config_lookup_string(&config, "pam_url.ssl.client_key", &opts->sslkey) ) + { + opts->sslkey = calloc(1, strlen(DEF_SSLKEY) + 1); + strcpy(opts->sslkey, DEF_SSLKEY); + } + + return PAM_SUCCESS; } @@ -166,7 +193,7 @@ int fetch_url(pam_handle_t *pamh, pam_url_opts opts) if( NULL == opts.passwd ) opts.passwd = calloc(1,1); - + post = calloc(1,strlen(opts.userfield) + strlen("=") + strlen(opts.user) + @@ -237,6 +264,30 @@ int fetch_url(pam_handle_t *pamh, pam_url_opts opts) return PAM_AUTH_ERR; } + if( CURLE_OK != curl_easy_setopt(eh, CURLOPT_SSLCERT, opts.sslcert) ) + { + curl_easy_cleanup(eh); + return PAM_AUTH_ERR; + } + + if( CURLE_OK != curl_easy_setopt(eh, CURLOPT_SSLCERTTYPE, "PEM") ) + { + curl_easy_cleanup(eh); + return PAM_AUTH_ERR; + } + + if( CURLE_OK != curl_easy_setopt(eh, CURLOPT_SSLKEY, opts.sslkey) ) + { + curl_easy_cleanup(eh); + return PAM_AUTH_ERR; + } + + if( CURLE_OK != curl_easy_setopt(eh, CURLOPT_SSLKEYTYPE, "PEM") ) + { + curl_easy_cleanup(eh); + return PAM_AUTH_ERR; + } + if( opts.ssl_verify_host == 1 ) { if( CURLE_OK != curl_easy_setopt(eh, CURLOPT_SSL_VERIFYHOST, 2) ) @@ -289,7 +340,7 @@ int fetch_url(pam_handle_t *pamh, pam_url_opts opts) } } -int check_psk(pam_url_opts opts) +int check_rc(pam_url_opts opts) { int ret=0; @@ -299,7 +350,7 @@ int check_psk(pam_url_opts opts) return PAM_AUTH_ERR; } - if( 0 != memcmp(opts.PSK, recvbuf, strlen(opts.PSK)) ) + if( 0 != memcmp(opts.RC, recvbuf, strlen(opts.RC)) ) ret++; if( 0 != ret ) diff --git a/pam_url.h b/pam_url.h index 1bf9250..86a4598 100644 --- a/pam_url.h +++ b/pam_url.h @@ -47,8 +47,8 @@ #define DEF_URL "https://www.example.org/" #endif -#ifndef DEF_PSK - #define DEF_PSK "presharedsecret" +#ifndef DEF_RETURNCODE + #define DEF_RETURNCODE "OK" #endif #ifndef DEF_USER @@ -63,6 +63,17 @@ #define DEF_EXTRA "&do=pam_url" #endif +#ifndef DEF_SSLCERT + #define DEF_SSLCERT "/etc/pki/pam_url_cert.pem" +#endif + +#ifndef DEF_SSLKEY + #define DEF_SSLKEY "/etc/pki/pam_url_key.pem" +#endif + +#ifndef DEF_PROMPT + #define DEF_PROMPT "Password: " +#endif #define true 1 #define false 0 @@ -71,13 +82,15 @@ int pam_url_debug; typedef struct pam_url_opts_ { char* url; - char* PSK; + char* RC; char* userfield; char* passwdfield; char* extrafield; char* mode; char* configfile; - + char* sslcert; + char* sslkey; + int ssl_verify_peer; int ssl_verify_host; @@ -89,7 +102,7 @@ void debug(pam_handle_t* pamh, const char *msg); int get_password(pam_handle_t* pamh, pam_url_opts* opts); int parse_opts(pam_url_opts* opts, int argc, const char** argv, int mode); int fetch_url(pam_handle_t *pamh, pam_url_opts opts); -int check_psk(pam_url_opts opts); +int check_rc(pam_url_opts opts); void cleanup(pam_url_opts* opts); #endif /* PAM_URL_H_ */ diff --git a/pam_url_account.c b/pam_url_account.c index 0bbee67..37ffe96 100644 --- a/pam_url_account.c +++ b/pam_url_account.c @@ -25,10 +25,10 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const c debug(pamh, "Could not fetch URL."); } - if( PAM_SUCCESS != check_psk(opts) ) + if( PAM_SUCCESS != check_rc(opts) ) { ret++; - debug(pamh, "Pre Shared Key differs from ours."); + debug(pamh, "Wrong Return Code."); } cleanup(&opts); diff --git a/pam_url_authenticate.c b/pam_url_authenticate.c index b21796d..0f42cae 100644 --- a/pam_url_authenticate.c +++ b/pam_url_authenticate.c @@ -11,7 +11,6 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv) { pam_url_opts opts; - int ret = 0; if ( PAM_SUCCESS != pam_get_item(pamh, PAM_USER, &opts.user) ) @@ -52,10 +51,10 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, debug(pamh, "Could not fetch URL."); } - if( PAM_SUCCESS != check_psk(opts) ) + if( PAM_SUCCESS != check_rc(opts) ) { ret++; - debug(pamh, "Pre Shared Key differs from ours."); + debug(pamh, "Wrong Return Code."); } cleanup(&opts); diff --git a/pam_url_password.c b/pam_url_password.c index d5a9a54..26c3b83 100644 --- a/pam_url_password.c +++ b/pam_url_password.c @@ -58,10 +58,10 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const c debug(pamh, "Could not fetch URL."); } - if( PAM_SUCCESS != check_psk(opts) ) + if( PAM_SUCCESS != check_rc(opts) ) { ret++; - debug(pamh, "Pre Shared Key differs from ours."); + debug(pamh, "Wrong Return Code."); } cleanup(&opts); diff --git a/pam_url_session.c b/pam_url_session.c index f7472a2..95fe208 100644 --- a/pam_url_session.c +++ b/pam_url_session.c @@ -33,10 +33,10 @@ PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, cons debug(pamh, "Could not fetch URL."); } - if( PAM_SUCCESS != check_psk(opts) ) + if( PAM_SUCCESS != check_rc(opts) ) { ret++; - debug(pamh, "Pre Shared Key differs from ours."); + debug(pamh, "Wrong Return Code"); } cleanup(&opts); @@ -83,10 +83,10 @@ PAM_EXTERN int pam_sm_close_session(pam_handle_t *pamh, int flags, int argc, con debug(pamh, "Could not fetch URL."); } - if( PAM_SUCCESS != check_psk(opts) ) + if( PAM_SUCCESS != check_rc(opts) ) { ret++; - debug(pamh, "Pre Shared Key differs from ours."); + debug(pamh, "Wrong Return Code."); } cleanup(&opts);