sesman: Remove unused authentication methods
The Kerberos module and pam_userpass modules are now unused: 1) On all supported systems, PAM provides a far superior way to integrate Kerberos support. 2) The pam_userpass module (https://github.com/openwall/pam_userpass) (which is a lovely idea) is no longer maintained.
This commit is contained in:
+1
-23
@@ -95,18 +95,10 @@ AC_ARG_ENABLE(ipv6, AS_HELP_STRING([--enable-ipv6],
|
||||
AC_ARG_ENABLE(ipv6only, AS_HELP_STRING([--enable-ipv6only],
|
||||
[Build IPv6-only (default: no)]),
|
||||
[], [enable_ipv6only=no])
|
||||
AC_ARG_ENABLE(kerberos, AS_HELP_STRING([--enable-kerberos],
|
||||
[Build kerberos support (prefer --enable-pam if available) (default: no)]),
|
||||
[], [enable_kerberos=no])
|
||||
AM_CONDITIONAL(SESMAN_KERBEROS, [test x$enable_kerberos = xyes])
|
||||
AC_ARG_ENABLE(bsd, AS_HELP_STRING([--enable-bsd],
|
||||
[Build BSD auth support (default: no)]),
|
||||
[], [enable_bsd=no])
|
||||
AM_CONDITIONAL(SESMAN_BSD, [test x$enable_bsd = xyes])
|
||||
AC_ARG_ENABLE(pamuserpass, AS_HELP_STRING([--enable-pamuserpass],
|
||||
[Build PAM userpass support (default: no)]),
|
||||
[], [enable_pamuserpass=no])
|
||||
AM_CONDITIONAL(SESMAN_PAMUSERPASS, [test x$enable_pamuserpass = xyes])
|
||||
AC_ARG_ENABLE(pam-config, AS_HELP_STRING([--enable-pam-config=CONF],
|
||||
[Select PAM config to install: arch, debian, redhat, suse, freebsd, macos, unix
|
||||
(default: autodetect)]))
|
||||
@@ -388,24 +380,10 @@ then
|
||||
AUTHMOD_OBJ=verify_user_bsd.lo
|
||||
AUTHMOD_LIB=
|
||||
fi
|
||||
if test x$enable_kerberos = xyes
|
||||
then
|
||||
auth_cnt=`expr $auth_cnt + 1`
|
||||
auth_mech="Kerberos"
|
||||
AUTHMOD_OBJ=verify_user_kerberos.lo
|
||||
AUTHMOD_LIB=-lkrb5
|
||||
fi
|
||||
if test x$enable_pamuserpass = xyes
|
||||
then
|
||||
auth_cnt=`expr $auth_cnt + 1`
|
||||
auth_mech="PAM userpass"
|
||||
AUTHMOD_OBJ=verify_user_pam_userpass.lo
|
||||
AUTHMOD_LIB="-lpam -lpam_userpass"
|
||||
fi
|
||||
|
||||
if test $auth_cnt -gt 1
|
||||
then
|
||||
AC_MSG_ERROR([--enable-pam, --enable-bsd, --enable-pamuserpass and --enable-kerberos are mutually exclusive])
|
||||
AC_MSG_ERROR([--enable-pam and --enable-bsd are mutually exclusive])
|
||||
fi
|
||||
|
||||
AC_SUBST([AUTHMOD_OBJ])
|
||||
|
||||
@@ -15,16 +15,8 @@ CLEANFILES = xrdp-sesman
|
||||
if SESMAN_NOPAM
|
||||
PAMFILE =
|
||||
else
|
||||
if SESMAN_PAMUSERPASS
|
||||
PAMFILE =
|
||||
else
|
||||
if SESMAN_KERBEROS
|
||||
PAMFILE =
|
||||
else
|
||||
PAMFILE = xrdp-sesman
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
pamddir = $(pamconfdir)
|
||||
|
||||
|
||||
@@ -45,9 +45,7 @@ module_LTLIBRARIES = \
|
||||
EXTRA_libsesman_la_SOURCES = \
|
||||
verify_user.c \
|
||||
verify_user_bsd.c \
|
||||
verify_user_kerberos.c \
|
||||
verify_user_pam.c \
|
||||
verify_user_pam_userpass.c
|
||||
verify_user_pam.c
|
||||
|
||||
# Make sure the right authentication module is pulled in
|
||||
libsesman_la_DEPENDENCIES = $(AUTHMOD_OBJ)
|
||||
|
||||
@@ -1,237 +0,0 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2013
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @file verify_user_kerberos.c
|
||||
* @brief Authenticate user using kerberos
|
||||
* @author Jay Sorg
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "arch.h"
|
||||
#include "sesman_auth.h"
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <krb5.h>
|
||||
|
||||
struct auth_info
|
||||
{
|
||||
krb5_context ctx;
|
||||
krb5_ccache cc;
|
||||
krb5_principal me;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
/* Logs a kerberos error code */
|
||||
static void
|
||||
log_kerberos_failure(krb5_context ctx, krb5_error_code code, const char *where)
|
||||
{
|
||||
const char *errstr = krb5_get_error_message(ctx, code);
|
||||
LOG(LOG_LEVEL_ERROR, "Kerberos call to %s failed [%s]", where, errstr);
|
||||
krb5_free_error_message(ctx, errstr);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
auth_end(struct auth_info *auth_info)
|
||||
{
|
||||
if (auth_info != NULL)
|
||||
{
|
||||
if (auth_info->me)
|
||||
{
|
||||
krb5_free_principal(auth_info->ctx, auth_info->me);
|
||||
}
|
||||
|
||||
if (auth_info->cc)
|
||||
{
|
||||
krb5_cc_close(auth_info->ctx, auth_info->cc);
|
||||
}
|
||||
|
||||
if (auth_info->ctx)
|
||||
{
|
||||
krb5_free_context(auth_info->ctx);
|
||||
}
|
||||
|
||||
g_memset(auth_info, 0, sizeof(*auth_info));
|
||||
g_free(auth_info);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Checks Kerberos can be used
|
||||
*
|
||||
* If all is well, an auth_info struct is returned */
|
||||
static struct auth_info *
|
||||
k5_begin(const char *username)
|
||||
{
|
||||
int ok = 0;
|
||||
struct auth_info *auth_info = g_new0(struct auth_info, 1);
|
||||
krb5_error_code code;
|
||||
|
||||
if (auth_info == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Out of memory in k5_begin()");
|
||||
}
|
||||
else if ((code = krb5_init_context(&auth_info->ctx)) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't init Kerberos context");
|
||||
}
|
||||
/* Determine the credentials cache to use */
|
||||
else if ((code = krb5_cc_default(auth_info->ctx, &auth_info->cc)) != 0)
|
||||
{
|
||||
log_kerberos_failure(auth_info->ctx, code, "krb5_cc_default");
|
||||
}
|
||||
/* Parse the username into a full principal */
|
||||
else if ((code = krb5_parse_name(auth_info->ctx,
|
||||
username, &auth_info->me)) != 0)
|
||||
{
|
||||
log_kerberos_failure(auth_info->ctx, code, "krb5_parse_name");
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = 1;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
auth_end(auth_info);
|
||||
auth_info = NULL;
|
||||
}
|
||||
|
||||
return auth_info;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns boolean */
|
||||
static enum scp_login_status
|
||||
k5_kinit(struct auth_info *auth_info, const char *password)
|
||||
{
|
||||
enum scp_login_status status = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
krb5_creds my_creds;
|
||||
krb5_error_code code = 0;
|
||||
|
||||
code = krb5_get_init_creds_password(auth_info->ctx,
|
||||
&my_creds, auth_info->me,
|
||||
password, NULL, NULL,
|
||||
0,
|
||||
NULL,
|
||||
NULL);
|
||||
if (code != 0)
|
||||
{
|
||||
log_kerberos_failure(auth_info->ctx, code,
|
||||
"krb5_get_init_creds_password");
|
||||
status = E_SCP_LOGIN_NOT_AUTHENTICATED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Try to store the creds in the credentials cache
|
||||
*/
|
||||
if ((code = krb5_cc_initialize(auth_info->ctx, auth_info->cc,
|
||||
auth_info->me)) != 0)
|
||||
{
|
||||
log_kerberos_failure(auth_info->ctx, code, "krb5_cc_initialize");
|
||||
}
|
||||
else if ((code = krb5_cc_store_cred(auth_info->ctx, auth_info->cc,
|
||||
&my_creds)) != 0)
|
||||
{
|
||||
log_kerberos_failure(auth_info->ctx, code, "krb5_cc_store_cred");
|
||||
}
|
||||
else
|
||||
{
|
||||
status = E_SCP_LOGIN_OK;
|
||||
}
|
||||
|
||||
/* Prevent double-free of the client principal */
|
||||
if (my_creds.client == auth_info->me)
|
||||
{
|
||||
my_creds.client = NULL;
|
||||
}
|
||||
|
||||
krb5_free_cred_contents(auth_info->ctx, &my_creds);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns non-NULL for success */
|
||||
struct auth_info *
|
||||
auth_userpass(const char *user, const char *pass,
|
||||
const char *client_ip, enum scp_login_status *errorcode)
|
||||
{
|
||||
enum scp_login_status status = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
struct auth_info *auth_info = k5_begin(user);
|
||||
|
||||
if (auth_info)
|
||||
{
|
||||
status = k5_kinit(auth_info, pass);
|
||||
if (status != E_SCP_LOGIN_OK)
|
||||
{
|
||||
auth_end(auth_info);
|
||||
auth_info = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (errorcode != NULL)
|
||||
{
|
||||
*errorcode = status;
|
||||
}
|
||||
|
||||
return auth_info;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns non-NULL for success */
|
||||
struct auth_info *
|
||||
auth_uds(const char *user, enum scp_login_status *errorcode)
|
||||
{
|
||||
struct auth_info *auth_info = k5_begin(user);
|
||||
|
||||
if (errorcode != NULL)
|
||||
{
|
||||
*errorcode =
|
||||
(auth_info != NULL) ? E_SCP_LOGIN_OK : E_SCP_LOGIN_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
return auth_info;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns error */
|
||||
int
|
||||
auth_start_session(struct auth_info *auth_info, const char *display)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
auth_set_env(struct auth_info *auth_info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -1,365 +0,0 @@
|
||||
/**
|
||||
* xrdp: A Remote Desktop Protocol server.
|
||||
*
|
||||
* Copyright (C) Jay Sorg 2004-2013
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @file verify_user_pam.c
|
||||
* @brief Authenticate user using pam
|
||||
* @author Jay Sorg
|
||||
*
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include <config_ac.h>
|
||||
#endif
|
||||
|
||||
#include "arch.h"
|
||||
#include "os_calls.h"
|
||||
#include "log.h"
|
||||
#include "string_calls.h"
|
||||
#include "sesman_auth.h"
|
||||
|
||||
#include <security/pam_userpass.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <security/pam_appl.h>
|
||||
|
||||
#define SERVICE "xrdp"
|
||||
|
||||
struct auth_info
|
||||
{
|
||||
pam_userpass_t userpass;
|
||||
int session_opened;
|
||||
int did_setcred;
|
||||
struct pam_conv pamc;
|
||||
pam_handle_t *ph;
|
||||
};
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/** Performs PAM operations common to login methods
|
||||
*
|
||||
* @param auth_info Module auth_info structure
|
||||
* @param client_ip Client IP if known, or NULL
|
||||
* @param need_pam_authenticate True if user must be authenticated as
|
||||
* well as authorized
|
||||
* @return Code describing the success of the operation
|
||||
*
|
||||
* The username is assumed to be supplied by the caller in
|
||||
* auth_info->userpass.user
|
||||
*/
|
||||
static enum scp_login_status
|
||||
common_pam_login(struct auth_info *auth_info,
|
||||
const char *client_ip,
|
||||
int need_pam_authenticate)
|
||||
{
|
||||
int perror;
|
||||
|
||||
perror = pam_start(SERVICE, auth_info->userpass.user,
|
||||
&(auth_info->pamc), &(auth_info->ph));
|
||||
|
||||
if (perror != PAM_SUCCESS)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_start failed: %s",
|
||||
pam_strerror(auth_info->ph, perror));
|
||||
pam_end(auth_info->ph, perror);
|
||||
return E_SCP_LOGIN_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
if (client_ip != NULL && client_ip[0] != '\0')
|
||||
{
|
||||
perror = pam_set_item(auth_info->ph, PAM_RHOST, client_ip);
|
||||
if (perror != PAM_SUCCESS)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_set_item(PAM_RHOST) failed: %s",
|
||||
pam_strerror(auth_info->ph, perror));
|
||||
}
|
||||
}
|
||||
|
||||
perror = pam_set_item(auth_info->ph, PAM_TTY, SERVICE);
|
||||
if (perror != PAM_SUCCESS)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_set_item(PAM_TTY) failed: %s",
|
||||
pam_strerror(auth_info->ph, perror));
|
||||
}
|
||||
|
||||
if (need_pam_authenticate)
|
||||
{
|
||||
perror = pam_authenticate(auth_info->ph, 0);
|
||||
|
||||
if (perror != PAM_SUCCESS)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_authenticate failed: %s",
|
||||
pam_strerror(auth_info->ph, perror));
|
||||
pam_end(auth_info->ph, perror);
|
||||
return E_SCP_LOGIN_NOT_AUTHENTICATED;
|
||||
}
|
||||
}
|
||||
/* From man page:
|
||||
The pam_acct_mgmt function is used to determine if the users account is
|
||||
valid. It checks for authentication token and account expiration and
|
||||
verifies access restrictions. It is typically called after the user has
|
||||
been authenticated.
|
||||
*/
|
||||
perror = pam_acct_mgmt(auth_info->ph, 0);
|
||||
|
||||
if (perror != PAM_SUCCESS)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_acct_mgmt failed: %s",
|
||||
pam_strerror(auth_info->ph, perror));
|
||||
pam_end(auth_info->ph, perror);
|
||||
return E_SCP_LOGIN_NOT_AUTHORIZED;
|
||||
}
|
||||
|
||||
return E_SCP_LOGIN_OK;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns non-NULL for success
|
||||
* Detailed error code is in the errorcode variable */
|
||||
|
||||
struct auth_info *
|
||||
auth_userpass(const char *user, const char *pass,
|
||||
const char *client_ip, enum scp_login_status *errorcode)
|
||||
{
|
||||
struct auth_info *auth_info;
|
||||
enum scp_login_status status;
|
||||
|
||||
auth_info = g_new0(struct auth_info, 1);
|
||||
if (auth_info == NULL)
|
||||
{
|
||||
status = E_SCP_LOGIN_NO_MEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
auth_info->userpass.user = user;
|
||||
auth_info->userpass.pass = pass;
|
||||
|
||||
auth_info->pamc.conv = &pam_userpass_conv;
|
||||
auth_info->pamc.appdata_ptr = &(auth_info->userpass);
|
||||
status = common_pam_login(auth_info, client_ip, 1);
|
||||
|
||||
if (status != E_SCP_LOGIN_OK)
|
||||
{
|
||||
g_free(auth_info);
|
||||
auth_info = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (errorcode != NULL)
|
||||
{
|
||||
*errorcode = status;
|
||||
}
|
||||
|
||||
return auth_info;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
struct auth_info *
|
||||
auth_uds(const char *user, enum scp_login_status *errorcode)
|
||||
{
|
||||
struct auth_info *auth_info;
|
||||
enum scp_login_status status;
|
||||
|
||||
auth_info = g_new0(struct auth_info, 1);
|
||||
if (auth_info == NULL)
|
||||
{
|
||||
status = E_SCP_LOGIN_NO_MEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
auth_info->userpass.user = user;
|
||||
status = common_pam_login(auth_info, NULL, 0);
|
||||
|
||||
if (status != E_SCP_LOGIN_OK)
|
||||
{
|
||||
g_free(auth_info);
|
||||
auth_info = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (errorcode != NULL)
|
||||
{
|
||||
*errorcode = status;
|
||||
}
|
||||
|
||||
return auth_info;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* returns error */
|
||||
static int
|
||||
auth_start_session_private(struct auth_info *auth_info, const char *display)
|
||||
{
|
||||
// For Linux and maybe other systems, pam_systemd needs to know the
|
||||
// session type in order to set the session up correctly
|
||||
const char *session_type;
|
||||
if (g_get_x11_display_from_display_string(display) >= 0)
|
||||
{
|
||||
session_type = "x11";
|
||||
}
|
||||
else
|
||||
{
|
||||
session_type = "wayland";
|
||||
}
|
||||
g_setenv_log("XDG_SESSION_TYPE", session_type, 1);
|
||||
|
||||
int error = pam_set_item(auth_info->ph, PAM_TTY, display);
|
||||
|
||||
if (error != PAM_SUCCESS)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_set_item(PAM_TTY) failed: %s",
|
||||
pam_strerror(auth_info->ph, error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
error = pam_setcred(auth_info->ph, PAM_ESTABLISH_CRED);
|
||||
|
||||
if (error != PAM_SUCCESS)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_setcred failed: %s",
|
||||
pam_strerror(auth_info->ph, error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
auth_info->did_setcred = 1;
|
||||
error = pam_open_session(auth_info->ph, 0);
|
||||
|
||||
if (error != PAM_SUCCESS)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_open_session failed: %s",
|
||||
pam_strerror(auth_info->ph, error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
auth_info->session_opened = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Main routine to start a session
|
||||
*
|
||||
* Calls the private routine and logs an additional error if the private
|
||||
* routine fails
|
||||
*/
|
||||
int
|
||||
auth_start_session(struct auth_info *auth_info, const char *display)
|
||||
{
|
||||
int result = auth_start_session_private(auth_info, display);
|
||||
if (result != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Can't start PAM session. See PAM logging for more info");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns error */
|
||||
static int
|
||||
auth_stop_session(struct auth_info *auth_info)
|
||||
{
|
||||
int rv = 0;
|
||||
int error;
|
||||
|
||||
if (auth_info->session_opened)
|
||||
{
|
||||
error = pam_close_session(auth_info->ph, 0);
|
||||
if (error != PAM_SUCCESS)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "pam_close_session failed: %s",
|
||||
pam_strerror(auth_info->ph, error));
|
||||
rv = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
auth_info->session_opened = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (auth_info->did_setcred)
|
||||
{
|
||||
pam_setcred(auth_info->ph, PAM_DELETE_CRED);
|
||||
auth_info->did_setcred = 0;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns error */
|
||||
/* cleanup */
|
||||
int
|
||||
auth_end(struct auth_info *auth_info)
|
||||
{
|
||||
if (auth_info != NULL)
|
||||
{
|
||||
if (auth_info->ph != 0)
|
||||
{
|
||||
auth_stop_session(auth_info);
|
||||
|
||||
pam_end(auth_info->ph, PAM_SUCCESS);
|
||||
auth_info->ph = 0;
|
||||
}
|
||||
}
|
||||
|
||||
g_free(auth_info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* returns error */
|
||||
/* set any pam env vars */
|
||||
int
|
||||
auth_set_env(struct auth_info *auth_info)
|
||||
{
|
||||
char **pam_envlist;
|
||||
char **pam_env;
|
||||
|
||||
if (auth_info != NULL)
|
||||
{
|
||||
/* export PAM environment */
|
||||
pam_envlist = pam_getenvlist(auth_info->ph);
|
||||
|
||||
if (pam_envlist != NULL)
|
||||
{
|
||||
for (pam_env = pam_envlist; *pam_env != NULL; ++pam_env)
|
||||
{
|
||||
char *str = *pam_env;
|
||||
char *eq_pos = strchr(str, '=');
|
||||
|
||||
if (eq_pos != NULL)
|
||||
{
|
||||
*eq_pos = '\0';
|
||||
g_setenv_log(str, eq_pos + 1, 1);
|
||||
}
|
||||
|
||||
g_free(str);
|
||||
}
|
||||
|
||||
g_free(pam_envlist);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user