Display PAM error in gateway setup, use domain name as IP/DNS, changed how the socket is closed

This commit is contained in:
ArvidNorr 2013-01-16 01:28:35 -08:00
parent b2c242f50e
commit a2bbbd8cc3
13 changed files with 174 additions and 41 deletions

View File

@ -41,7 +41,7 @@ typedef int (*ttrans_conn_in)(struct trans* self, struct trans* new_self);
struct trans
{
tbus sck;
tbus sck; /* socket handle */
int mode; /* 1 tcp, 2 unix socket */
int status;
int type1; /* 1 listener 2 server 3 client */

View File

@ -819,6 +819,25 @@ xrdp_mcs_send(struct xrdp_mcs *self, struct stream *s, int chan)
return 0;
}
/**
* Internal help function to close the socket
* @param self
*/
void close_rdp_socket(struct xrdp_mcs *self)
{
if(self->iso_layer->tcp_layer)
{
if(self->iso_layer->tcp_layer->trans)
{
g_tcp_close(self->iso_layer->tcp_layer->trans->sck);
self->iso_layer->tcp_layer->trans->sck = 0 ;
g_writeln("xrdp_mcs_disconnect - socket closed");
return ;
}
}
g_writeln("Failed to close socket");
}
/*****************************************************************************/
/* returns error */
int APP_CC
@ -833,7 +852,8 @@ xrdp_mcs_disconnect(struct xrdp_mcs *self)
if (xrdp_iso_init(self->iso_layer, s) != 0)
{
free_stream(s);
DEBUG((" out xrdp_mcs_disconnect error"));
close_rdp_socket(self);
DEBUG((" out xrdp_mcs_disconnect error - 1"));
return 1;
}
@ -844,11 +864,13 @@ xrdp_mcs_disconnect(struct xrdp_mcs *self)
if (xrdp_iso_send(self->iso_layer, s) != 0)
{
free_stream(s);
DEBUG((" out xrdp_mcs_disconnect error"));
close_rdp_socket(self);
DEBUG((" out xrdp_mcs_disconnect error - 2"));
return 1;
}
free_stream(s);
DEBUG((" out xrdp_mcs_disconnect"));
close_rdp_socket(self);
DEBUG(("xrdp_mcs_disconnect - close sent"));
return 0;
}

View File

@ -36,7 +36,7 @@
*
*/
long DEFAULT_CC
auth_userpass(char* user, char* pass);
auth_userpass(char* user, char* pass, int *errorcode);
/**
*

View File

@ -35,8 +35,9 @@ scp_v0_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s)
int display = 0;
tbus data;
struct session_item *s_item;
int errorcode = 0 ;
data = auth_userpass(s->username, s->password);
data = auth_userpass(s->username, s->password,&errorcode);
if (s->type == SCP_GW_AUTHENTICATION)
{
@ -47,14 +48,14 @@ scp_v0_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s)
if (1 == access_login_allowed(s->username))
{
/* the user is member of the correct groups. */
scp_v0s_replyauthentication(c, 0);
scp_v0s_replyauthentication(c, errorcode);
log_message(LOG_LEVEL_INFO, "Access permitted for user: %s",
s->username);
/* g_writeln("Connection allowed"); */
}
else
{
scp_v0s_replyauthentication(c, 3);
scp_v0s_replyauthentication(c, 32+3); /* all first 32 are reserved for PAM errors */
log_message(LOG_LEVEL_INFO, "Username okey but group problem for "
"user: %s", s->username);
/* g_writeln("user password ok, but group problem"); */
@ -65,7 +66,7 @@ scp_v0_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s)
/* g_writeln("username or password error"); */
log_message(LOG_LEVEL_INFO, "Username or password error for user: %s",
s->username);
scp_v0s_replyauthentication(c, 2);
scp_v0s_replyauthentication(c, errorcode);
}
auth_end(data);

View File

@ -50,7 +50,7 @@ scp_v1_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s)
retries = g_cfg->sec.login_retry;
current_try = retries;
data = auth_userpass(s->username, s->password);
data = auth_userpass(s->username, s->password,NULL);
/*LOG_DBG("user: %s\npass: %s", s->username, s->password);*/
while ((!data) && ((retries == 0) || (current_try > 0)))
@ -65,7 +65,7 @@ scp_v1_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s)
{
case SCP_SERVER_STATE_OK:
/* all ok, we got new username and password */
data = auth_userpass(s->username, s->password);
data = auth_userpass(s->username, s->password,NULL);
/* one try less */
if (current_try > 0)

View File

@ -42,7 +42,7 @@ scp_v1_mng_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s)
int scount;
int end = 0;
data = auth_userpass(s->username, s->password);
data = auth_userpass(s->username, s->password,NULL);
/*LOG_DBG("user: %s\npass: %s", s->username, s->password);*/
if (!data)

View File

@ -98,9 +98,11 @@ get_service_name(char *service_name)
}
/******************************************************************************/
/* returns long, zero is no go */
/* returns long, zero is no go
Stores the detailed error code in the errorcode variable*/
long DEFAULT_CC
auth_userpass(char *user, char *pass)
auth_userpass(char *user, char *pass, int *errorcode)
{
int error;
struct t_auth_info *auth_info;
@ -116,6 +118,9 @@ auth_userpass(char *user, char *pass)
if (error != PAM_SUCCESS)
{
if(errorcode!=NULL){
*errorcode = error ;
}
g_printf("pam_start failed: %s\r\n", pam_strerror(auth_info->ph, error));
g_free(auth_info);
return 0;
@ -125,16 +130,27 @@ auth_userpass(char *user, char *pass)
if (error != PAM_SUCCESS)
{
if(errorcode!=NULL){
*errorcode = error ;
}
g_printf("pam_authenticate failed: %s\r\n",
pam_strerror(auth_info->ph, error));
g_free(auth_info);
return 0;
}
/* 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.
*/
error = pam_acct_mgmt(auth_info->ph, 0);
if (error != PAM_SUCCESS)
{
if(errorcode!=NULL){
*errorcode = error ;
}
g_printf("pam_acct_mgmt failed: %s\r\n",
pam_strerror(auth_info->ph, error));
g_free(auth_info);

View File

@ -177,7 +177,7 @@ void DEFAULT_CC
pipe_sig(int sig_num)
{
/* do nothing */
g_writeln("got SIGPIPE(%d)", sig_num);
g_writeln("got XRDP SIGPIPE(%d)", sig_num);
}
/*****************************************************************************/

View File

@ -315,7 +315,18 @@ xrdp_wm_show_edits(struct xrdp_wm *self, struct xrdp_bitmap *combo)
{
self->login_window->focused_control = b;
}
/*Use the domain name as the destination IP/DNS
This is useful in a gateway setup.*/
if (g_strncmp(name, "ip", 255) == 0)
{
/* If the first char in the domain name is '_' we use the domain name as IP*/
if(self->session->client_info->domain[0]=='_')
{
g_strncpy(b->caption1, &self->session->client_info->domain[1], 255);
b->edit_pos = g_mbstowcs(0, b->caption1, 0);
}
}
if (g_strncmp(name, "username", 255) == 0)
{
g_strncpy(b->caption1, self->session->client_info->username, 255);

View File

@ -17,10 +17,12 @@
*
* module manager
*/
#define ACCESS
#include "xrdp.h"
#include "log.h"
#define ACCESS
#ifdef ACCESS
#include "security/_pam_types.h"
#endif
/*****************************************************************************/
struct xrdp_mm *APP_CC
@ -187,9 +189,17 @@ xrdp_mm_send_login(struct xrdp_mm *self)
}
/* send domain */
index = g_strlen(self->wm->client_info->domain);
out_uint16_be(s, index);
out_uint8a(s, self->wm->client_info->domain, index);
if(self->wm->client_info->domain[0]!='_')
{
index = g_strlen(self->wm->client_info->domain);
out_uint16_be(s, index);
out_uint8a(s, self->wm->client_info->domain, index);
}
else
{
out_uint16_be(s, 0);
/* out_uint8a(s, "", 0); */
}
/* send program / shell */
index = g_strlen(self->wm->client_info->program);
@ -1060,12 +1070,12 @@ xrdp_mm_sesman_data_in(struct trans *trans)
int access_control(char *username, char *password, char *srv)
{
int reply;
int rec = 1; // failure
int rec = 32+1; /* 32 is reserved for PAM failures this means connect failure */
struct stream *in_s;
struct stream *out_s;
unsigned long version;
unsigned short int dummy;
unsigned short int ok;
unsigned short int pAM_errorcode;
unsigned short int code;
unsigned long size;
int index;
@ -1117,17 +1127,17 @@ int access_control(char *username, char *password, char *srv)
if ((size == 14) && (version == 0))
{
in_uint16_be(in_s, code);
in_uint16_be(in_s, ok);
in_uint16_be(in_s, pAM_errorcode); /* this variable holds the PAM error code if the variable is >32 it is a "invented" code */
in_uint16_be(in_s, dummy);
if (code != 4)
if (code != 4) /*0x04 means SCP_GW_AUTHENTICATION*/
{
log_message(LOG_LEVEL_ERROR, "Returned cmd code from "
"sesman is corrupt");
}
else
{
rec = ok; /* here we read the reply from the access control */
rec = pAM_errorcode; /* here we read the reply from the access control */
}
}
else
@ -1189,6 +1199,82 @@ void cleanup_states(struct xrdp_mm *self)
self-> usechansrv = 0; /* true if chansrvport is set in xrdp.ini or using sesman */
}
}
#ifdef ACCESS
const char *getPAMError(const int pamError)
{
switch(pamError){
case PAM_SUCCESS:
return "Success";
case PAM_OPEN_ERR:
return "dlopen() failure";
case PAM_SYMBOL_ERR:
return "Symbol not found";
case PAM_SERVICE_ERR:
return "Error in service module";
case PAM_SYSTEM_ERR:
return "System error";
case PAM_BUF_ERR:
return "Memory buffer error";
case PAM_PERM_DENIED:
return "Permission denied";
case PAM_AUTH_ERR:
return "Authentication failure";
case PAM_CRED_INSUFFICIENT:
return "Insufficient credentials to access authentication data";
case PAM_AUTHINFO_UNAVAIL:
return "Authentication service cannot retrieve authentication info.";
case PAM_USER_UNKNOWN:
return "User not known to the underlying authentication module";
case PAM_MAXTRIES:
return "Have exhasted maximum number of retries for service.";
case PAM_NEW_AUTHTOK_REQD:
return "Authentication token is no longer valid; new one required.";
case PAM_ACCT_EXPIRED:
return "User account has expired";
case PAM_CRED_UNAVAIL:
return "Authentication service cannot retrieve user credentials";
case PAM_CRED_EXPIRED:
return "User credentials expired";
case PAM_CRED_ERR:
return "Failure setting user credentials";
case PAM_NO_MODULE_DATA:
return "No module specific data is present";
case PAM_BAD_ITEM:
return "Bad item passed to pam_*_item()";
case PAM_CONV_ERR:
return "Conversation error";
case PAM_AUTHTOK_ERR:
return "Authentication token manipulation error";
case PAM_AUTHTOK_LOCK_BUSY:
return "Authentication token lock busy";
case PAM_AUTHTOK_DISABLE_AGING:
return "Authentication token aging disabled";
case PAM_TRY_AGAIN:
return "Failed preliminary check by password service";
case PAM_IGNORE:
return "Please ignore underlying account module";
case PAM_MODULE_UNKNOWN:
return "Module is unknown";
case PAM_AUTHTOK_EXPIRED:
return "Authentication token expired";
case PAM_CONV_AGAIN:
return "Conversation is waiting for event";
case PAM_INCOMPLETE:
return "Application needs to call libpam again";
case 32+1:
return "Error connecting to PAM";
case 32+3:
return "Username okey but group problem";
default:{
char replytxt[80];
g_sprintf(replytxt,"Not defined PAM error:%d",pamError);
return replytxt ;
}
}
}
#endif
/*****************************************************************************/
int APP_CC
xrdp_mm_connect(struct xrdp_mm *self)
@ -1282,7 +1368,6 @@ xrdp_mm_connect(struct xrdp_mm *self)
{
int reply;
char replytxt[80];
char replymessage[4][80] = {"Ok", "Sesman connect failure", "User or password error", "Privilege group error"};
xrdp_wm_log_msg(self->wm, "Please wait, we now perform access control...");
/* g_writeln("we use pam modules to check if we can approve this user"); */
@ -1300,15 +1385,8 @@ xrdp_mm_connect(struct xrdp_mm *self)
/* access_control return 0 on success */
reply = access_control(pam_auth_username, pam_auth_password, pam_auth_sessionIP);
if (reply >= 0 && reply < 4)
{
g_sprintf(replytxt, "Reply from access control: %s", replymessage[reply]);
}
else
{
g_sprintf(replytxt, "Reply from access control undefined");
}
g_sprintf(replytxt, "Reply from access control: %s", getPAMError(reply));
xrdp_wm_log_msg(self->wm, replytxt);
log_message(LOG_LEVEL_INFO, replytxt);

View File

@ -197,14 +197,14 @@ xrdp_process_main_loop(struct xrdp_process *self)
break;
}
}
/* send disconnect message if possible */
libxrdp_disconnect(self->session);
}
else
{
g_writeln("xrdp_process_main_loop: libxrdp_process_incomming failed");
}
/* Run end in module */
xrdp_process_mod_end(self);
libxrdp_exit(self->session);
self->session = 0;

View File

@ -540,7 +540,12 @@ xrdp_wm_init(struct xrdp_wm *self)
names->auto_free = 1;
values = list_create();
values->auto_free = 1;
g_strncpy(section_name, self->session->client_info->domain, 255);
/* domain names that starts with '_' are reserved for IP/DNS to simplify
* for the user in a gateway setup */
if(self->session->client_info->domain[0]!='_')
{
g_strncpy(section_name, self->session->client_info->domain, 255);
}
if (section_name[0] == 0)
{

View File

@ -137,7 +137,7 @@ void DEFAULT_CC
pipe_sig(int sig_num)
{
/* do nothing */
g_writeln("got SIGPIPE(%d)", sig_num);
g_writeln("got XRDP WIN SIGPIPE(%d)", sig_num);
}
/*****************************************************************************/