|
|
#include <security/pam_modules.h> | #include <security/pam_modules.h> |
#include <pam_mount.h> | #include <pam_mount.h> |
| |
|
#include <smbpwman/smbpw.h> |
|
|
gboolean debug; | gboolean debug; |
config_t config; | config_t config; |
pam_args_t args; | pam_args_t args; |
|
|
void clean_system_authtok(pam_handle_t * pamh, void *data, int errcode) | void clean_system_authtok(pam_handle_t * pamh, void *data, int errcode) |
{ | { |
/* FIXME: not binary password safe */ | /* FIXME: not binary password safe */ |
/* FIXME: valgrind does not like -- called previously? |
|
if (data) { | if (data) { |
memset(data, 0x00, strlen(data)); | memset(data, 0x00, strlen(data)); |
free(data); | free(data); |
} | } |
*/ |
|
} | } |
| |
/* ============================ converse () ================================ */ | /* ============================ converse () ================================ */ |
|
|
const void *tmp = NULL; | const void *tmp = NULL; |
|
const void *dummy = NULL; |
assert(pamh); |
void *dummy2 = NULL; |
|
|
ret = PAM_AUTH_ERR; | ret = PAM_AUTH_ERR; |
goto _return; | goto _return; |
} | } |
if ((ret = |
if (smbpw_verify_socket_path(SOCKET_NAME) < 0) { |
pam_set_data(pamh, "pam_mount_system_authtok", authtok, |
l0g("pam_mount: smbpwman socket path %s is insecure", |
clean_system_authtok)) != PAM_SUCCESS) { |
SOCKET_NAME); |
l0g("pam_mount: %s\n", |
ret = PAM_AUTH_ERR; |
"error trying to save authtok for session code"); |
|
goto _return; | goto _return; |
} | } |
|
if ((ret = smbpw_store(config.user, authtok)) < 0) { |
|
l0g("pam_mount: error %i caching password", ret); |
|
ret = PAM_AUTH_ERR; |
|
goto _return; |
|
} |
|
/*ensure smbpw_store is called the same |
|
number of times as smbpw_retrieve so no |
|
credentials are left lying around */ |
|
if ((pam_get_data(pamh, "pam_mount_pw_stored", &dummy)) == PAM_SUCCESS) { |
|
authtok = smbpw_retrieve(config.user); |
|
} |
|
pam_set_data(pamh, "pam_mount_pw_stored", dummy2, NULL); |
_return: | _return: |
assert(ret != PAM_SUCCESS |
|
|| pam_get_data(pamh, "pam_mount_system_authtok", |
|
&tmp) == PAM_SUCCESS); |
|
assert(ret != PAM_SUCCESS || tmp); |
|
| |
return ret; | return ret; |
} | } |
|
|
int vol; | int vol; |
int ret = PAM_SUCCESS; | int ret = PAM_SUCCESS; |
char *system_authtok; | char *system_authtok; |
|
const char *pam_user; |
| |
assert(pamh); | assert(pamh); |
| |
|
|
if (chdir("/")) | if (chdir("/")) |
l0g("pam_mount %s\n", "could not chdir"); | l0g("pam_mount %s\n", "could not chdir"); |
if (config.user == NULL) { | if (config.user == NULL) { |
l0g("pam_mount: username not read: pam_mount not conf. for auth?\n"); |
/* If config.user is not stored, try reading it as the |
/* do NOT return PAM_SERVICE_ERR or root will not be able |
authenticate and open_session may have been called in different |
* to su to other users */ |
processes (eg openssh) */ |
goto _return; |
if ((ret = pam_get_user(pamh, &pam_user, NULL)) != PAM_SUCCESS) |
|
{ |
|
l0g("pam_mount: username not read and couldn't be fetched: pam_mount not conf. for auth?\n"); |
|
/* do NOT return PAM_SERVICE_ERR or root will not |
|
* be able to su to other users */ |
|
goto _return; |
|
} |
|
config.user=strdup(pam_user); |
} | } |
if (strlen(config.user) > MAX_PAR) { | if (strlen(config.user) > MAX_PAR) { |
l0g("pam_mount: username %s is too long\n", config.user); | l0g("pam_mount: username %s is too long\n", config.user); |
ret = PAM_SERVICE_ERR; | ret = PAM_SERVICE_ERR; |
goto _return; | goto _return; |
} | } |
if ((ret = |
if (!(system_authtok = smbpw_retrieve(config.user))) |
pam_get_data(pamh, "pam_mount_system_authtok", |
|
(const void **) &system_authtok)) != PAM_SUCCESS) |
|
{ | { |
l0g("pam_mount: %s\n", | l0g("pam_mount: %s\n", |
"error trying to retrieve authtok from auth code"); |
"error trying to retrieve authtok from smbpwman cache"); |
goto _return; | goto _return; |
} | } |
if (!readconfig(config.user, CONFIGFILE, 1, &config)) { | if (!readconfig(config.user, CONFIGFILE, 1, &config)) { |
|
|
config.volume[vol].volume); | config.volume[vol].volume); |
} | } |
/* end root priv. */ | /* end root priv. */ |
/* Paranoia? */ |
|
clean_system_authtok(pamh, system_authtok, 0); |
|
/* This code needs root priv. */ | /* This code needs root priv. */ |
modify_pm_count(&config, config.user, "1"); | modify_pm_count(&config, config.user, "1"); |
/* end root priv. */ | /* end root priv. */ |
| |
_return: | _return: |
|
/* Paranoia? */ |
|
clean_system_authtok(pamh, system_authtok, 0); |
w4rn("pam_mount: done opening session\n"); | w4rn("pam_mount: done opening session\n"); |
return ret; | return ret; |
} | } |
|
|
int vol; | int vol; |
/* FIXME: this currently always returns PAM_SUCCESS should return something else when errors occur but only after all unmounts are attempted??? */ | /* FIXME: this currently always returns PAM_SUCCESS should return something else when errors occur but only after all unmounts are attempted??? */ |
int ret = PAM_SUCCESS; | int ret = PAM_SUCCESS; |
|
const char *pam_user; |
| |
assert(pamh); | assert(pamh); |
| |
|
|
w4rn("pam_mount: real and effective user ID are %d and %d.\n", | w4rn("pam_mount: real and effective user ID are %d and %d.\n", |
getuid(), geteuid()); | getuid(), geteuid()); |
if (config.user == NULL) { | if (config.user == NULL) { |
l0g("pam_mount: username not read: pam_mount not conf. for auth?\n"); |
if ((ret = pam_get_user(pamh, &pam_user, NULL)) != PAM_SUCCESS) |
/* do NOT return PAM_SERVICE_ERR or root will not be able |
{ |
* to su to other users */ |
l0g("pam_mount: username not read and couldn't be fetched: pam_mount not conf. for auth?\n"); |
goto _return; |
/* do NOT return PAM_SERVICE_ERR or root will not |
|
* be able to su to other users */ |
|
goto _return; |
|
} |
|
config.user=strdup(pam_user); |
} | } |
if (config.volcount <= 0) | if (config.volcount <= 0) |
w4rn("pam_mount: %s\n", "volcount is zero"); | w4rn("pam_mount: %s\n", "volcount is zero"); |