summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/trans.h2
-rw-r--r--libxrdp/xrdp_mcs.c28
-rw-r--r--sesman/auth.h2
-rw-r--r--sesman/scp_v0.c9
-rw-r--r--sesman/scp_v1.c4
-rw-r--r--sesman/scp_v1_mng.c2
-rw-r--r--sesman/verify_user_pam.c22
-rw-r--r--xrdp/xrdp.c2
-rw-r--r--xrdp/xrdp_login_wnd.c13
-rw-r--r--xrdp/xrdp_mm.c118
-rw-r--r--xrdp/xrdp_process.c4
-rw-r--r--xrdp/xrdp_wm.c7
-rw-r--r--xrdp/xrdpwin.c2
13 files changed, 174 insertions, 41 deletions
diff --git a/common/trans.h b/common/trans.h
index 36d08a7c..1133477a 100644
--- a/common/trans.h
+++ b/common/trans.h
@@ -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 */
diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c
index 77c0d10d..e5481c9c 100644
--- a/libxrdp/xrdp_mcs.c
+++ b/libxrdp/xrdp_mcs.c
@@ -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;
}
diff --git a/sesman/auth.h b/sesman/auth.h
index 09bec2e9..39acc0b8 100644
--- a/sesman/auth.h
+++ b/sesman/auth.h
@@ -36,7 +36,7 @@
*
*/
long DEFAULT_CC
-auth_userpass(char* user, char* pass);
+auth_userpass(char* user, char* pass, int *errorcode);
/**
*
diff --git a/sesman/scp_v0.c b/sesman/scp_v0.c
index da6ab919..6ecb47b1 100644
--- a/sesman/scp_v0.c
+++ b/sesman/scp_v0.c
@@ -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);
diff --git a/sesman/scp_v1.c b/sesman/scp_v1.c
index 295fbce4..d3f0ab7f 100644
--- a/sesman/scp_v1.c
+++ b/sesman/scp_v1.c
@@ -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)
diff --git a/sesman/scp_v1_mng.c b/sesman/scp_v1_mng.c
index 0e20007d..9d1da0f5 100644
--- a/sesman/scp_v1_mng.c
+++ b/sesman/scp_v1_mng.c
@@ -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)
diff --git a/sesman/verify_user_pam.c b/sesman/verify_user_pam.c
index b81398de..b7a7bef7 100644
--- a/sesman/verify_user_pam.c
+++ b/sesman/verify_user_pam.c
@@ -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);
diff --git a/xrdp/xrdp.c b/xrdp/xrdp.c
index fb6fd5dd..2ed2c8fd 100644
--- a/xrdp/xrdp.c
+++ b/xrdp/xrdp.c
@@ -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);
}
/*****************************************************************************/
diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c
index fc4cf125..08abfedb 100644
--- a/xrdp/xrdp_login_wnd.c
+++ b/xrdp/xrdp_login_wnd.c
@@ -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);
diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c
index 9b0de186..0f2fae2a 100644
--- a/xrdp/xrdp_mm.c
+++ b/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);
diff --git a/xrdp/xrdp_process.c b/xrdp/xrdp_process.c
index e3b846ea..070dc697 100644
--- a/xrdp/xrdp_process.c
+++ b/xrdp/xrdp_process.c
@@ -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;
diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c
index 24362f54..27a794a0 100644
--- a/xrdp/xrdp_wm.c
+++ b/xrdp/xrdp_wm.c
@@ -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)
{
diff --git a/xrdp/xrdpwin.c b/xrdp/xrdpwin.c
index ed6fa4c5..b6bf8fc8 100644
--- a/xrdp/xrdpwin.c
+++ b/xrdp/xrdpwin.c
@@ -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);
}
/*****************************************************************************/