Display PAM error in gateway setup, use domain name as IP/DNS, changed how the socket is closed
This commit is contained in:
parent
b2c242f50e
commit
a2bbbd8cc3
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@
|
||||
*
|
||||
*/
|
||||
long DEFAULT_CC
|
||||
auth_userpass(char* user, char* pass);
|
||||
auth_userpass(char* user, char* pass, int *errorcode);
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -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);
|
||||
|
118
xrdp/xrdp_mm.c
118
xrdp/xrdp_mm.c
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
Loading…
Reference in New Issue
Block a user