You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
329 lines
7.8 KiB
329 lines
7.8 KiB
#include <stdlib.h> |
|
#include <string.h> |
|
#include <unistd.h> |
|
|
|
#include "entrance.h" |
|
|
|
/* |
|
* ... |
|
* pam_start(...); Initializes the PAM library |
|
* ... |
|
* if ( ! pam_authenticate(...) ) Autenticates using modules |
|
* error_exit(); |
|
* ... |
|
* if ( ! pam-acct_mgmt(...) ) Checks for a valid, unexpired account and |
|
* verifies access restrictions with "account" modules |
|
* error_exit(); |
|
* ... |
|
* pam_setcred(...) Sets extra credentials, e.g. a Kerberos ticket |
|
* ... |
|
* pam_open_session(...); Sets up the session with "session" modules |
|
* do_stuff(); |
|
* |
|
* pam_close_session(...); Tear-down session using the "session" modules |
|
* pam_end(...); |
|
* */ |
|
static int _entrance_pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr); |
|
|
|
static struct pam_conv _pam_conversation; |
|
static pam_handle_t* _pam_handle = NULL; |
|
static int last_result; |
|
static char *_login = NULL; |
|
static char *_passwd = NULL; |
|
|
|
|
|
|
|
static int |
|
_entrance_pam_conv(int num_msg, const struct pam_message **msg, |
|
struct pam_response **resp, void *appdata_ptr EINA_UNUSED) |
|
{ |
|
int i, result = PAM_SUCCESS; |
|
*resp = (struct pam_response *) calloc(num_msg, sizeof(struct pam_response)); |
|
for (i = 0; i < num_msg; ++i) |
|
{ |
|
resp[i]->resp=0; |
|
resp[i]->resp_retcode=0; |
|
switch(msg[i]->msg_style) |
|
{ |
|
case PAM_PROMPT_ECHO_ON: |
|
// We assume PAM is asking for the username |
|
PT("echo on\n"); |
|
resp[i]->resp = _login; |
|
break; |
|
|
|
case PAM_PROMPT_ECHO_OFF: |
|
PT("echo off\n"); |
|
resp[i]->resp = _passwd; |
|
_passwd = NULL; |
|
break; |
|
case PAM_ERROR_MSG: |
|
PT("error msg\n"); |
|
case PAM_TEXT_INFO: |
|
PT("info "); |
|
fprintf(stderr, "%s\n", msg[i]->msg); |
|
break; |
|
case PAM_SUCCESS: |
|
PT("success :)\n"); |
|
break; |
|
default: |
|
PT("default\n"); |
|
} |
|
if (result != PAM_SUCCESS) break; |
|
} |
|
if (result != PAM_SUCCESS) |
|
{ |
|
for (i = 0; i < num_msg; ++i) |
|
{ |
|
if (resp[i]->resp==0) continue; |
|
free(resp[i]->resp); |
|
resp[i]->resp=0; |
|
} |
|
free(*resp); |
|
*resp=0; |
|
} |
|
return result; |
|
} |
|
|
|
static char * |
|
_get_running_username(void) |
|
{ |
|
char *result; |
|
struct passwd *pwent = NULL; |
|
pwent = getpwuid(getuid()); |
|
result = strdup(pwent->pw_name); |
|
endpwent(); |
|
return (result); |
|
} |
|
|
|
|
|
int |
|
entrance_pam_open_session(void) |
|
{ |
|
last_result = pam_setcred(_pam_handle, PAM_ESTABLISH_CRED); |
|
switch (last_result) |
|
{ |
|
case PAM_CRED_ERR: |
|
case PAM_USER_UNKNOWN: |
|
PT("PAM user unknow\n"); |
|
return 1; |
|
case PAM_AUTH_ERR: |
|
case PAM_PERM_DENIED: |
|
PT("PAM error on login password\n"); |
|
return 1; |
|
default: |
|
PT("PAM open warning unknow error\n"); |
|
return 1; |
|
case PAM_SUCCESS: |
|
break; |
|
} |
|
last_result = pam_open_session(_pam_handle, 0); |
|
switch(last_result) |
|
{ |
|
default: |
|
//case PAM_SESSION_ERROR: ??? |
|
pam_setcred(_pam_handle, PAM_DELETE_CRED); |
|
entrance_pam_end(); |
|
case PAM_SUCCESS: |
|
break; |
|
} |
|
return 0; |
|
} |
|
|
|
void |
|
entrance_pam_close_session(const Eina_Bool opened) |
|
{ |
|
PT("PAM close session\n"); |
|
last_result = pam_close_session(_pam_handle, PAM_SILENT); |
|
switch (last_result) |
|
{ |
|
default: |
|
//case PAM_SESSION_ERROR: |
|
PT("error on close session\n"); |
|
pam_setcred(_pam_handle, PAM_DELETE_CRED); |
|
entrance_pam_end(); |
|
case PAM_SUCCESS: |
|
break; |
|
} |
|
if (opened) |
|
{ |
|
last_result = pam_setcred(_pam_handle, PAM_DELETE_CRED); |
|
switch(last_result) |
|
{ |
|
default: |
|
case PAM_CRED_ERR: |
|
case PAM_CRED_UNAVAIL: |
|
case PAM_CRED_EXPIRED: |
|
case PAM_USER_UNKNOWN: |
|
entrance_pam_end(); |
|
case PAM_SUCCESS: |
|
break; |
|
} |
|
} |
|
} |
|
|
|
int |
|
entrance_pam_end(void) |
|
{ |
|
int result; |
|
result = pam_end(_pam_handle, last_result); |
|
_pam_handle = NULL; |
|
return result; |
|
} |
|
|
|
int |
|
entrance_pam_authenticate(void) |
|
{ |
|
last_result = pam_authenticate(_pam_handle, 0); |
|
switch (last_result) |
|
{ |
|
case PAM_ABORT: |
|
case PAM_AUTHINFO_UNAVAIL: |
|
PT("PAM error !\n"); |
|
entrance_pam_end(); |
|
return 1; |
|
case PAM_USER_UNKNOWN: |
|
PT("PAM user unknow error !\n"); |
|
return 1; |
|
case PAM_MAXTRIES: |
|
PT("PAM max tries error !\n"); |
|
entrance_server_client_wait(); |
|
return 1; |
|
case PAM_CRED_INSUFFICIENT: |
|
PT("PAM don't have sufficient credential to authenticate !\n"); |
|
return 1; |
|
case PAM_AUTH_ERR: |
|
PT("PAM authenticate error !\n"); |
|
return 1; |
|
default: |
|
PT("PAM auth warning unknow error\n"); |
|
return 1; |
|
case PAM_SUCCESS: |
|
break; |
|
} |
|
last_result=pam_acct_mgmt(_pam_handle, PAM_SILENT); |
|
switch(last_result) |
|
{ |
|
default: |
|
//case PAM_NEW_AUTHTOKEN_REQD: |
|
case PAM_ACCT_EXPIRED: |
|
PT("PAM user acct expired error\n"); |
|
entrance_pam_end(); |
|
return 1; |
|
case PAM_USER_UNKNOWN: |
|
PT("PAM user unknow error\n"); |
|
entrance_pam_end(); |
|
return 1; |
|
case PAM_AUTH_ERR: |
|
PT("PAM auth error\n"); |
|
return 1; |
|
case PAM_PERM_DENIED: |
|
PT("PAM perm_denied error\n"); |
|
return 1; |
|
case PAM_SUCCESS: |
|
break; |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
int |
|
entrance_pam_init(const char *service, const char *display, const char *user) |
|
{ |
|
int status; |
|
|
|
if (!service || !*service) goto pam_error; |
|
if (!display || !*display) goto pam_error; |
|
|
|
_pam_conversation.conv = _entrance_pam_conv; |
|
_pam_conversation.appdata_ptr = NULL; |
|
|
|
if (_pam_handle) entrance_pam_end(); |
|
status = pam_start(service, user, &_pam_conversation, &_pam_handle); |
|
|
|
if (status != 0) goto pam_error; |
|
status = entrance_pam_item_set(ENTRANCE_PAM_ITEM_TTY, display); |
|
if (status != 0) goto pam_error; |
|
status = entrance_pam_item_set(ENTRANCE_PAM_ITEM_RUSER, _get_running_username()); |
|
if (status != 0) goto pam_error; |
|
// status = entrance_pam_item_set(ENTRANCE_PAM_ITEM_RHOST, "localhost"); |
|
// if (status != 0) goto pam_error; |
|
return 0; |
|
|
|
pam_error: |
|
PT("PAM error !!!\n"); |
|
return 1; |
|
} |
|
|
|
int |
|
entrance_pam_item_set(ENTRANCE_PAM_ITEM_TYPE type, const void *value) |
|
{ |
|
last_result = pam_set_item(_pam_handle, type, value); |
|
if (last_result == PAM_SUCCESS) { |
|
return 0; |
|
} |
|
|
|
PT("PAM error: %d on %d\n", last_result, type); |
|
return 1; |
|
} |
|
|
|
const void * |
|
entrance_pam_item_get(ENTRANCE_PAM_ITEM_TYPE type) |
|
{ |
|
const void *data; |
|
last_result = pam_get_item(_pam_handle, type, &data); |
|
switch (last_result) { |
|
default: |
|
case PAM_SYSTEM_ERR: |
|
entrance_pam_end(); |
|
PT("error on pam item get\n"); |
|
case PAM_PERM_DENIED: /* Here data was NULL */ |
|
case PAM_SUCCESS: |
|
break; |
|
} |
|
return data; |
|
} |
|
|
|
int |
|
entrance_pam_env_set(const char *env, const char *value) |
|
{ |
|
char buf[1024]; |
|
if (!env || !value) return 1; |
|
snprintf(buf, sizeof(buf), "%s=%s", env, value); |
|
last_result = pam_putenv(_pam_handle, buf); |
|
switch (last_result) |
|
{ |
|
default: |
|
case PAM_PERM_DENIED: |
|
case PAM_ABORT: |
|
case PAM_BUF_ERR: |
|
entrance_pam_end(); |
|
return 1; |
|
case PAM_SUCCESS: |
|
break; |
|
} |
|
return 0; |
|
|
|
} |
|
|
|
char ** |
|
entrance_pam_env_list_get(void) |
|
{ |
|
return pam_getenvlist(_pam_handle); |
|
} |
|
|
|
void |
|
entrance_pam_shutdown(void) |
|
{ |
|
} |
|
|
|
int |
|
entrance_pam_auth_set(const char *login, const char *passwd) |
|
{ |
|
if (!login) |
|
return 1; |
|
_login = strdup(login); |
|
if (passwd) |
|
_passwd = strdup(passwd); |
|
return 0; |
|
} |
|
|
|
|