xrdp/xrdp-fate318398-change-expired-password.patch
Dirk Mueller f047e239d0 Accepting request 423916 from home:zhangxiaofei:branches:X11:RemoteDesktop
- Add xrdp-disable-8-bpp-vnc-support.patch:
  Disable 8 bpp vnc support. Xvnc drops support for 8 bpp since
  1.4.0. Trying to launch Xvnc in 8 bpp will cause it to dump core
  (bsc#991059).
- Add obs source services:
  + tar_scm
  + recompress
  + set_version
- Update to version 0.9.0~git.1456906198.f422461:
  Fix tarball naming from 0.9.0git to 0.9.0~git to conform openSUSE
  naming scheme for pre-release version.
  + Numlock out of sync fix
  + neutrinordp: minor changes, coding style, log level
  + Update faq-compile.txt
  + Change to allow authentication against all authentication
    methods.
  + Add details for crypt_level=fips to man page
  + libxrdp: no logic change, tabs to spaces
  + libxrdp: opps, fix typeo
  + Fix "\ _" on jp keyboard
  + xrdp_keyboard.ini: Fix jp keyboard model
  + update xorgxrdp
  + add keyboard options to xrdp_client_info
  + xorgxrdp=68412e5
- Add an extra legacy service action force_stop:
  Forcefully killing xrdp processes when it cannot be stopped
  normally.
  Usage:
    $ service xrdp force_stop
    or

OBS-URL: https://build.opensuse.org/request/show/423916
OBS-URL: https://build.opensuse.org/package/show/X11:RemoteDesktop/xrdp?expand=0&rev=5
2016-09-21 11:37:09 +00:00

846 lines
30 KiB
Diff

From 7eed33d99e93432c2b425a8ce1d2955b3532da39 Mon Sep 17 00:00:00 2001
From: Felix Zhang <fezhang@suse.com>
Date: Mon, 1 Aug 2016 17:26:41 +0800
Subject: [PATCH] FATE#318398: Enable xrdp to allow a required password change
for users
---
sesman/auth.h | 2 +
sesman/libscp/libscp_session.c | 30 ++++++++
sesman/libscp/libscp_types.h | 2 +
sesman/libscp/libscp_v0.c | 23 ++++--
sesman/libscp/libscp_v0.h | 2 +-
sesman/scp_v0.c | 13 +++-
sesman/verify_user_pam.c | 95 ++++++++++++++++++++++++
xrdp/xrdp_login_wnd.c | 155 +++++++++++++++++++++++++++++++++++++-
xrdp/xrdp_mm.c | 164 ++++++++++++++++++++++++++++++-----------
xrdp/xrdp_types.h | 1 +
xrdp/xrdp_wm.c | 41 ++++++++++-
11 files changed, 475 insertions(+), 53 deletions(-)
diff --git a/sesman/auth.h b/sesman/auth.h
index e06b9eb..ee33e94 100644
--- a/sesman/auth.h
+++ b/sesman/auth.h
@@ -106,4 +106,6 @@ auth_check_pwd_chg(char* user);
int DEFAULT_CC
auth_change_pwd(char* user, char* newpwd);
+int DEFAULT_CC
+auth_change_pwd_pam(char* user, char* pass, char* newpwd);
#endif
diff --git a/sesman/libscp/libscp_session.c b/sesman/libscp/libscp_session.c
index d25fc64..35bc223 100644
--- a/sesman/libscp/libscp_session.c
+++ b/sesman/libscp/libscp_session.c
@@ -71,6 +71,10 @@ scp_session_set_type(struct SCP_SESSION *s, tui8 type)
s->type = SCP_GW_AUTHENTICATION;
break;
+ case SCP_GW_CHAUTHTOK:
+ s->type = SCP_GW_CHAUTHTOK;
+ break;
+
case SCP_SESSION_TYPE_MANAGE:
s->type = SCP_SESSION_TYPE_MANAGE;
s->mng = (struct SCP_MNG_DATA *)g_malloc(sizeof(struct SCP_MNG_DATA), 1);
@@ -231,6 +235,32 @@ scp_session_set_password(struct SCP_SESSION *s, char *str)
/*******************************************************************/
int
+scp_session_set_newpass(struct SCP_SESSION *s, char *str)
+{
+ if (0 == str)
+ {
+ log_message(LOG_LEVEL_WARNING, "[session:%d] set_newpass: null newpass", __LINE__);
+ return 1;
+ }
+
+ if (0 != s->newpass)
+ {
+ g_free(s->newpass);
+ }
+
+ s->newpass = g_strdup(str);
+
+ if (0 == s->newpass)
+ {
+ log_message(LOG_LEVEL_WARNING, "[session:%d] set_newpass: strdup error", __LINE__);
+ return 1;
+ }
+
+ return 0;
+}
+
+/*******************************************************************/
+int
scp_session_set_domain(struct SCP_SESSION *s, char *str)
{
if (0 == str)
diff --git a/sesman/libscp/libscp_types.h b/sesman/libscp/libscp_types.h
index de85186..f6be582 100644
--- a/sesman/libscp/libscp_types.h
+++ b/sesman/libscp/libscp_types.h
@@ -47,6 +47,7 @@
* XRDP sends this command to let sesman verify if the user is allowed
* to use the gateway */
#define SCP_GW_AUTHENTICATION 0x04
+#define SCP_GW_CHAUTHTOK 0x05
#define SCP_ADDRESS_TYPE_IPV4 0x00
#define SCP_ADDRESS_TYPE_IPV6 0x01
@@ -81,6 +82,7 @@ struct SCP_SESSION
char locale[18];
char* username;
char* password;
+ char* newpass;
char* hostname;
tui8 addr_type;
tui32 ipv4addr;
diff --git a/sesman/libscp/libscp_v0.c b/sesman/libscp/libscp_v0.c
index 8cf1340..2b3d203 100644
--- a/sesman/libscp/libscp_v0.c
+++ b/sesman/libscp/libscp_v0.c
@@ -306,9 +306,8 @@ scp_v0s_accept(struct SCP_CONNECTION *c, struct SCP_SESSION **s, int skipVchk)
}
}
}
- else if (code == SCP_GW_AUTHENTICATION)
+ else if (code == SCP_GW_AUTHENTICATION || code == SCP_GW_CHAUTHTOK)
{
- /* g_writeln("Command is SCP_GW_AUTHENTICATION"); */
session = scp_session_create();
if (0 == session)
@@ -318,7 +317,7 @@ scp_v0s_accept(struct SCP_CONNECTION *c, struct SCP_SESSION **s, int skipVchk)
}
scp_session_set_version(session, version);
- scp_session_set_type(session, SCP_GW_AUTHENTICATION);
+ scp_session_set_type(session, code);
/* reading username */
in_uint16_be(c->in_s, sz);
buf[sz] = '\0';
@@ -344,6 +343,19 @@ scp_v0s_accept(struct SCP_CONNECTION *c, struct SCP_SESSION **s, int skipVchk)
/* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting password", __LINE__); */
return SCP_SERVER_STATE_INTERNAL_ERR;
}
+ if (code == SCP_GW_CHAUTHTOK)
+ {
+ /* reading new password */
+ in_uint16_be(c->in_s, sz);
+ buf[sz] = '\0';
+ in_uint8a(c->in_s, buf, sz);
+
+ if (0 != scp_session_set_newpass(session, buf))
+ {
+ scp_session_destroy(session);
+ return SCP_SERVER_STATE_INTERNAL_ERR;
+ }
+ }
}
else
{
@@ -399,12 +411,13 @@ scp_v0s_deny_connection(struct SCP_CONNECTION *c)
/******************************************************************************/
enum SCP_SERVER_STATES_E
-scp_v0s_replyauthentication(struct SCP_CONNECTION *c, unsigned short int value)
+scp_v0s_replyauthentication(struct SCP_CONNECTION *c, unsigned short int value, tui8 type)
{
out_uint32_be(c->out_s, 0); /* version */
out_uint32_be(c->out_s, 14); /* size */
/* cmd SCP_GW_AUTHENTICATION means authentication reply */
- out_uint16_be(c->out_s, SCP_GW_AUTHENTICATION);
+ /* cmd SCP_GW_CHAUTHTOK means chauthtok reply */
+ out_uint16_be(c->out_s, type);
out_uint16_be(c->out_s, value); /* reply code */
out_uint16_be(c->out_s, 0); /* dummy data */
s_mark_end(c->out_s);
diff --git a/sesman/libscp/libscp_v0.h b/sesman/libscp/libscp_v0.h
index 16e49e0..3199db0 100644
--- a/sesman/libscp/libscp_v0.h
+++ b/sesman/libscp/libscp_v0.h
@@ -79,6 +79,6 @@ scp_v0s_deny_connection(struct SCP_CONNECTION* c);
* @return
*/
enum SCP_SERVER_STATES_E
-scp_v0s_replyauthentication(struct SCP_CONNECTION* c, unsigned short int value);
+scp_v0s_replyauthentication(struct SCP_CONNECTION* c, unsigned short int value, tui8 type);
#endif
diff --git a/sesman/scp_v0.c b/sesman/scp_v0.c
index ce528d4..3fc788f 100644
--- a/sesman/scp_v0.c
+++ b/sesman/scp_v0.c
@@ -37,6 +37,13 @@ scp_v0_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s)
struct session_item *s_item;
int errorcode = 0 ;
+ if (s->type == SCP_GW_CHAUTHTOK)
+ {
+ errorcode = auth_change_pwd_pam(s->username, s->password, s->newpass);
+ scp_v0s_replyauthentication(c, errorcode, SCP_GW_CHAUTHTOK);
+ return ;
+ }
+
data = auth_userpass(s->username, s->password,&errorcode);
if (s->type == SCP_GW_AUTHENTICATION)
@@ -48,14 +55,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, errorcode);
+ scp_v0s_replyauthentication(c, errorcode, SCP_GW_AUTHENTICATION);
log_message(LOG_LEVEL_INFO, "Access permitted for user: %s",
s->username);
/* g_writeln("Connection allowed"); */
}
else
{
- scp_v0s_replyauthentication(c, 32+3); /* all first 32 are reserved for PAM errors */
+ scp_v0s_replyauthentication(c, 32 + 3, SCP_GW_AUTHENTICATION); /* 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"); */
@@ -66,7 +73,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, errorcode);
+ scp_v0s_replyauthentication(c, errorcode, SCP_GW_AUTHENTICATION);
}
auth_end(data);
diff --git a/sesman/verify_user_pam.c b/sesman/verify_user_pam.c
index a2b3f93..4eb61fa 100644
--- a/sesman/verify_user_pam.c
+++ b/sesman/verify_user_pam.c
@@ -34,6 +34,7 @@ struct t_user_pass
{
char user[256];
char pass[256];
+ char newpwd[256];
};
struct t_auth_info
@@ -82,6 +83,55 @@ verify_pam_conv(int num_msg, const struct pam_message **msg,
}
/******************************************************************************/
+static int DEFAULT_CC
+chauth_pam_conv(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *appdata_ptr)
+{
+ int i;
+ struct pam_response *reply;
+ struct t_user_pass *user_pass;
+
+ reply = g_malloc(sizeof(struct pam_response) * num_msg, 1);
+
+ for (i = 0; i < num_msg; i++)
+ {
+ switch (msg[i]->msg_style)
+ {
+ case PAM_PROMPT_ECHO_ON: /* username */
+ user_pass = appdata_ptr;
+ reply[i].resp = g_strdup(user_pass->user);
+ reply[i].resp_retcode = PAM_SUCCESS;
+ break;
+ case PAM_PROMPT_ECHO_OFF: /* password */
+ user_pass = appdata_ptr;
+ /* only prompt for old password starts with '('
+ old pass: "(current) UNIX password:"
+ new pass: "New password:"
+ retype new pass: "Retype new password:" */
+ if (*(msg[i]->msg) == '(')
+ {
+ reply[i].resp = g_strdup(user_pass->pass);
+ }
+ else
+ {
+ reply[i].resp = g_strdup(user_pass->newpwd);
+ }
+ reply[i].resp_retcode = PAM_SUCCESS;
+ break;
+ case PAM_TEXT_INFO: /* useless messages */
+ break;
+ default:
+ g_printf("unknown in verify_pam_conv\r\n");
+ g_free(reply);
+ return PAM_CONV_ERR;
+ }
+ }
+
+ *resp = reply;
+ return PAM_SUCCESS;
+}
+
+/******************************************************************************/
static void DEFAULT_CC
get_service_name(char *service_name)
{
@@ -309,3 +359,48 @@ auth_set_env(long in_val)
return 0;
}
+/******************************************************************************/
+/* returns boolean */
+/* update to the new pass */
+int DEFAULT_CC
+auth_change_pwd_pam(char *user, char *pass, char *newpwd)
+{
+ int error;
+ struct t_auth_info *auth_info;
+ char service_name[256];
+
+ get_service_name(service_name);
+ auth_info = g_malloc(sizeof(struct t_auth_info), 1);
+ g_strncpy(auth_info->user_pass.user, user, 255);
+ g_strncpy(auth_info->user_pass.pass, pass, 255);
+ g_strncpy(auth_info->user_pass.newpwd, newpwd, 255);
+ auth_info->pamc.conv = &chauth_pam_conv;
+ auth_info->pamc.appdata_ptr = &(auth_info->user_pass);
+ error = pam_start(service_name, 0, &(auth_info->pamc), &(auth_info->ph));
+
+ if (error != PAM_SUCCESS)
+ {
+ g_printf("pam_start failed: %s\r\n", pam_strerror(auth_info->ph, error));
+ pam_end(auth_info->ph, error);
+ g_free(auth_info);
+ return error;
+ }
+
+ error = pam_set_item(auth_info->ph, PAM_TTY, service_name);
+ if (error != PAM_SUCCESS)
+ {
+ g_printf("pam_set_item failed: %s\r\n",
+ pam_strerror(auth_info->ph, error));
+ }
+
+ error = pam_chauthtok(auth_info->ph, PAM_CHANGE_EXPIRED_AUTHTOK);
+ if (error != PAM_SUCCESS)
+ {
+ g_printf("pam_chauthtok failed: %s\r\n",
+ pam_strerror(auth_info->ph, error));
+ pam_end(auth_info->ph, error);
+ g_free(auth_info);
+ return error;
+ }
+ return error;
+}
diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c
index 357b4e2..c74eedd 100644
--- a/xrdp/xrdp_login_wnd.c
+++ b/xrdp/xrdp_login_wnd.c
@@ -178,7 +178,14 @@ xrdp_wm_cancel_clicked(struct xrdp_bitmap *wnd)
{
if (wnd->wm != 0)
{
- if (wnd->wm->pro_layer != 0)
+ struct xrdp_bitmap *b1;
+ b1 = xrdp_bitmap_get_child_by_id(wnd, 201);
+ if (b1 != 0 )
+ {
+ /* go back to login window when canceling new password creation */
+ xrdp_wm_set_login_mode(wnd->wm, 0);
+ }
+ else if (wnd->wm->pro_layer != 0)
{
g_set_wait_obj(wnd->wm->pro_layer->self_term_event);
}
@@ -236,7 +243,29 @@ xrdp_wm_ok_clicked(struct xrdp_bitmap *wnd)
}
else
{
- log_message(LOG_LEVEL_ERROR, "Combo is 0 - potential programming error");
+ struct xrdp_bitmap *b1;
+ struct xrdp_bitmap *b2;
+ struct xrdp_bitmap *b3;
+ b1 = xrdp_bitmap_get_child_by_id(wnd, 201);
+ b2 = xrdp_bitmap_get_child_by_id(wnd, 203);
+ b3 = xrdp_bitmap_get_child_by_id(wnd, 250);
+ if (b1 != 0 && b2 != 0 && b3 != 0)
+ {
+ if (g_strlen(b1->caption1) > 0 && g_strncmp (b1->caption1, b2->caption1, 255) == 0)
+ {
+ list_add_item (wm->mm->login_names,(tbus)g_strdup("newpass"));
+ list_add_item (wm->mm->login_values,(tbus)g_strdup(b2->caption1));
+ xrdp_wm_set_login_mode (wm, 22);
+ }
+ else
+ {
+ xrdp_wm_set_login_mode(wm, 20);
+ }
+ }
+ else
+ {
+ log_message(LOG_LEVEL_ERROR, "Window not recognized - potential programming error");
+ }
}
return 0;
@@ -520,6 +549,31 @@ xrdp_wm_login_notify(struct xrdp_bitmap *wnd,
return 0;
}
+/*****************************************************************************/
+/* change new password window events go here */
+static int DEFAULT_CC
+xrdp_wm_newpass_notify(struct xrdp_bitmap *wnd,
+ struct xrdp_bitmap *sender,
+ int msg, long param1, long param2)
+{
+ if (wnd->modal_dialog != 0 && msg != 100)
+ {
+ return 0;
+ }
+
+ if (msg == 1) /* click */
+ {
+ if (sender->id == 2) /* cancel button */
+ {
+ xrdp_wm_cancel_clicked(wnd);
+ }
+ else if (sender->id == 3) /* ok button */
+ {
+ xrdp_wm_ok_clicked(wnd);
+ }
+ }
+ return 0;
+}
/******************************************************************************/
static int APP_CC
@@ -767,6 +821,103 @@ xrdp_login_wnd_create(struct xrdp_wm *self)
return 0;
}
+/******************************************************************************/
+int APP_CC
+xrdp_newpass_wnd_create(struct xrdp_wm *self)
+{
+ struct xrdp_bitmap *but;
+ struct xrdp_cfg_globals *globals;
+ int i;
+
+ globals = &self->xrdp_config->cfg_globals;
+
+ self->newpass_window = xrdp_bitmap_create(globals->ls_width, globals->ls_height, self->screen->bpp,
+ WND_TYPE_WND, self);
+ list_add_item(self->screen->child_list, (long)self->newpass_window);
+ self->newpass_window->parent = self->screen;
+ self->newpass_window->owner = self->screen;
+ self->newpass_window->bg_color = globals->ls_bg_color;
+
+ self->newpass_window->left = self->screen->width / 2 -
+ self->newpass_window->width / 2;
+
+ self->newpass_window->top = self->screen->height / 2 -
+ self->newpass_window->height / 2;
+
+ self->newpass_window->notify = xrdp_wm_newpass_notify;
+
+ set_string(&self->newpass_window->caption1, "Input new password");
+
+ /* OK button */
+ but = xrdp_bitmap_create(globals->ls_btn_ok_width, globals->ls_btn_ok_height,
+ self->screen->bpp, WND_TYPE_BUTTON, self);
+ list_add_item(self->newpass_window->child_list, (long)but);
+ but->parent = self->newpass_window;
+ but->owner = self->newpass_window;
+ but->left = globals->ls_btn_ok_x_pos;
+ but->top = globals->ls_btn_ok_y_pos;
+ but->id = 3;
+ set_string(&but->caption1, "OK");
+ but->tab_stop = 1;
+ self->newpass_window->default_button = but;
+
+ /* Cancel button */
+ but = xrdp_bitmap_create(globals->ls_btn_cancel_width,
+ globals->ls_btn_cancel_height, self->screen->bpp,
+ WND_TYPE_BUTTON, self);
+ list_add_item(self->newpass_window->child_list, (long)but);
+ but->parent = self->newpass_window;
+ but->owner = self->newpass_window;
+ but->left = globals->ls_btn_cancel_x_pos;
+ but->top = globals->ls_btn_cancel_y_pos;
+ but->id = 2;
+ set_string(&but->caption1, "Cancel");
+ but->tab_stop = 1;
+ self->newpass_window->esc_button = but;
+
+ /* labels and edits */
+ /* id starts between 200 and 249 */
+ char captions [][256] = {"New Pass", "Confirm"};
+ for (i = 0; i < 2; i++)
+ {
+ but = xrdp_bitmap_create(95, DEFAULT_EDIT_H, self->screen->bpp,
+ WND_TYPE_LABEL, self);
+ list_add_item(self->newpass_window->child_list, (long)but);
+ but->parent = self->newpass_window;
+ but->owner = self->newpass_window;
+ but->left = globals->ls_label_x_pos;
+ but->top = globals->ls_input_y_pos + (DEFAULT_COMBO_H +5) * i;
+ but->id = 200 + 2 * i;
+ set_string(&but->caption1, captions[i]);
+
+ but = xrdp_bitmap_create(DEFAULT_EDIT_W, DEFAULT_EDIT_H, self->screen->bpp,
+ WND_TYPE_EDIT, self);
+ list_add_item(self->newpass_window->child_list, (long)but);
+ but->parent = self->newpass_window;
+ but->owner = self->newpass_window;
+ but->left = globals->ls_input_x_pos;
+ but->top = globals->ls_input_y_pos + (DEFAULT_COMBO_H +5) * i;
+ but->id = 201 + 2 * i;
+ but->pointer = 1;
+ but->tab_stop = 1;
+ but->caption1 = (char *)g_malloc(256, 1);
+ but->password_char = '*';
+ }
+ /* error message label */
+ but = xrdp_bitmap_create (300, DEFAULT_EDIT_H, self->screen->bpp,
+ WND_TYPE_LABEL, self);
+ list_add_item(self->newpass_window->child_list, (long)but);
+ but->parent = self->newpass_window;
+ but->owner = self->newpass_window;
+ but->left = globals->ls_label_x_pos;
+ but->top = globals->ls_input_y_pos + (DEFAULT_COMBO_H +5) * 2;
+ but->id = 250;
+ but->caption1 = (char *)g_malloc(256, 1);
+ set_string(&but->caption1, "");
+
+ return 0;
+}
+
/**
* Load configuration from xrdp.ini file
*
diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c
index 76957ad..0ab173b 100644
--- a/xrdp/xrdp_mm.c
+++ b/xrdp/xrdp_mm.c
@@ -1425,7 +1425,7 @@ xrdp_mm_sesman_data_in(struct trans *trans)
/*********************************************************************/
/* return 0 on success */
static int APP_CC
-access_control(char *username, char *password, char *srv)
+access_control(char *username, char *password, char *newpass, char *srv, int type)
{
int reply;
int rec = 32+1; /* 32 is reserved for PAM failures this means connect failure */
@@ -1451,7 +1451,8 @@ access_control(char *username, char *password, char *srv)
make_stream(out_s);
init_stream(out_s, 500);
s_push_layer(out_s, channel_hdr, 8);
- out_uint16_be(out_s, 4); /*0x04 means SCP_GW_AUTHENTICATION*/
+ out_uint16_be(out_s, type); /*0x04 means SCP_GW_AUTHENTICATION*/
+ /*0x05 means SCP_GW_CHAUTHTOK*/
index = g_strlen(username);
out_uint16_be(out_s, index);
out_uint8a(out_s, username, index);
@@ -1459,6 +1460,14 @@ access_control(char *username, char *password, char *srv)
index = g_strlen(password);
out_uint16_be(out_s, index);
out_uint8a(out_s, password, index);
+
+ if (type == 5)
+ {
+ index = g_strlen(newpass);
+ out_uint16_be(out_s, index);
+ out_uint8a(out_s, newpass, index);
+ }
+
s_mark_end(out_s);
s_pop_layer(out_s, channel_hdr);
out_uint32_be(out_s, 0); /* version */
@@ -1488,15 +1497,19 @@ access_control(char *username, char *password, char *srv)
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) /*0x04 means SCP_GW_AUTHENTICATION*/
+ if (code == 4) /*0x04 means SCP_GW_AUTHENTICATION*/
{
- log_message(LOG_LEVEL_ERROR, "Returned cmd code from "
- "sesman is corrupt");
+ rec = pAM_errorcode; /* here we read the reply from the access control */
}
- else
+ else if (code == 5) /*0x05 means SCP_GW_CHAUTHTOK*/
{
rec = pAM_errorcode; /* here we read the reply from the access control */
}
+ else
+ {
+ log_message(LOG_LEVEL_ERROR, "Returned cmd code from "
+ "sesman is corrupt");
+ }
}
else
{
@@ -1709,7 +1722,7 @@ xrdp_mm_connect(struct xrdp_mm *self)
char chansrvport[256];
#ifdef ACCESS
#ifndef USE_NOPAM
- int use_pam_auth = 0;
+ int use_pam_auth_explicit = 0;
char pam_auth_sessionIP[256];
char pam_auth_password[256];
char pam_auth_username[256];
@@ -1752,7 +1765,7 @@ xrdp_mm_connect(struct xrdp_mm *self)
#ifndef USE_NOPAM
else if (g_strcasecmp(name, "pamusername") == 0)
{
- use_pam_auth = 1;
+ use_pam_auth_explicit = 1;
g_strncpy(pam_auth_username, value, 255);
}
else if (g_strcasecmp(name, "pamsessionmng") == 0)
@@ -1783,51 +1796,67 @@ xrdp_mm_connect(struct xrdp_mm *self)
#ifdef ACCESS
#ifndef USE_NOPAM
- if (use_pam_auth)
+ int reply;
+ char replytxt[128];
+ char pam_error[128];
+ const char *additionalError;
+ 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"); */
+
+ /* use pam either way, copy from normal user name when not explicitly inputed */
+ if (use_pam_auth_explicit == 0)
{
- int reply;
- char replytxt[128];
- char pam_error[128];
- const char *additionalError;
- xrdp_wm_log_msg(self->wm, "Please wait, we now perform access control...");
+ log_message(LOG_LEVEL_DEBUG, "pam parameters not defined, copy from user input");
+ g_strncpy(pam_auth_username, username, 255);
+ g_strncpy(pam_auth_password, password, 255);
+ g_strncpy(pam_auth_sessionIP, "127.0.0.1", 255);
+ }
- /* g_writeln("we use pam modules to check if we can approve this user"); */
- if (!g_strncmp(pam_auth_username, "same", 255))
- {
- log_message(LOG_LEVEL_DEBUG, "pamusername copied from username - same: %s", username);
- g_strncpy(pam_auth_username, username, 255);
- }
+ if (!g_strncmp(pam_auth_username, "same", 255))
+ {
+ log_message(LOG_LEVEL_DEBUG, "pamusername copied from username - same: %s", username);
+ g_strncpy(pam_auth_username, username, 255);
+ }
- if (!g_strncmp(pam_auth_password, "same", 255))
- {
- log_message(LOG_LEVEL_DEBUG, "pam_auth_password copied from username - same: %s", password);
- g_strncpy(pam_auth_password, password, 255);
- }
+ if (!g_strncmp(pam_auth_password, "same", 255))
+ {
+ log_message(LOG_LEVEL_DEBUG, "pam_auth_password copied from username - same: %s", password);
+ g_strncpy(pam_auth_password, password, 255);
+ }
- /* access_control return 0 on success */
- reply = access_control(pam_auth_username, pam_auth_password, pam_auth_sessionIP);
+ /* access_control return 0 on success */
+ reply = access_control(pam_auth_username, pam_auth_password, NULL, pam_auth_sessionIP, 4);
- g_sprintf(replytxt, "Reply from access control: %s",
- getPAMError(reply, pam_error, 127));
+ g_sprintf(replytxt, "Reply from access control: %s",
+ getPAMError(reply, pam_error, 127));
- xrdp_wm_log_msg(self->wm, replytxt);
- log_message(LOG_LEVEL_INFO, replytxt);
- additionalError = getPAMAdditionalErrorInfo(reply, self);
- if (additionalError)
+ xrdp_wm_log_msg(self->wm, replytxt);
+ log_message(LOG_LEVEL_INFO, replytxt);
+ additionalError = getPAMAdditionalErrorInfo(reply, self);
+ if (additionalError)
+ {
+ g_snprintf(replytxt, 127, "%s", additionalError);
+ if (replytxt[0])
{
- g_snprintf(replytxt, 127, "%s", additionalError);
- if (replytxt[0])
- {
- xrdp_wm_log_msg(self->wm, replytxt);
- }
+ xrdp_wm_log_msg(self->wm, replytxt);
}
+ }
+
+ if (reply != 0)
+ {
+ /* show PAM errors */
+ xrdp_wm_show_log(self->wm);
- if (reply != 0)
+ if (reply == PAM_NEW_AUTHTOK_REQD)
{
- rv = 1;
- return rv;
+ /* show new password window */
+ xrdp_wm_set_login_mode(self->wm, 20);
}
+ rv = 1;
+ return rv;
}
+
#endif
#endif
@@ -1923,6 +1952,59 @@ xrdp_mm_connect(struct xrdp_mm *self)
}
/*****************************************************************************/
+/* return 0 on success */
+int APP_CC
+xrdp_mm_change_expired_password(struct xrdp_mm *self)
+{
+ int rv = -1;
+ int index;
+ int count;
+ int old_idx;
+ int new_idx;
+ char *username;
+ char *password;
+ char *newpass;
+ char sessionIP[256];
+ char *name;
+ char *value;
+
+ username = 0;
+ password = 0;
+ count = self->login_names->count;
+
+ for (index = 0; index < count; index++)
+ {
+ name = (char *)list_get_item(self->login_names, index);
+ value = (char *)list_get_item(self->login_values, index);
+
+ if (g_strcasecmp(name, "username") == 0)
+ {
+ username = value;
+ }
+ else if (g_strcasecmp(name, "password") == 0)
+ {
+ password = value;
+ old_idx = index;
+ }
+ else if (g_strcasecmp(name, "newpass") == 0)
+ {
+ newpass = value;
+ new_idx = index;
+ }
+ g_strncpy(sessionIP, "127.0.0.1", 255);
+ }
+ rv = access_control(username, password, newpass, sessionIP, 5);
+ if (rv == 0)
+ {
+ list_remove_item (self->login_names, old_idx);
+ list_remove_item (self->login_values, old_idx);
+ list_add_item (self->login_names, (tbus)g_strdup("password"));
+ list_add_item (self->login_values, (tbus)g_strdup(newpass));
+ }
+ return rv;
+}
+
+/*****************************************************************************/
int APP_CC
xrdp_mm_get_wait_objs(struct xrdp_mm *self,
tbus *read_objs, int *rcount,
diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h
index 29aaac8..498e8dd 100644
--- a/xrdp/xrdp_types.h
+++ b/xrdp/xrdp_types.h
@@ -335,6 +335,7 @@ struct xrdp_wm
struct xrdp_cache* cache;
int palette[256];
struct xrdp_bitmap* login_window;
+ struct xrdp_bitmap* newpass_window;
/* generic colors */
int black;
int grey;
diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c
index 39bd038..7661408 100644
--- a/xrdp/xrdp_wm.c
+++ b/xrdp/xrdp_wm.c
@@ -1786,6 +1786,34 @@ xrdp_wm_login_mode_changed(struct xrdp_wm *self)
self->dragging = 0;
xrdp_wm_set_login_mode(self, 11);
}
+ else if (self->login_mode == 20)
+ {
+ /* keep log window open */
+ if (self->log_wnd == 0)
+ {
+ xrdp_wm_delete_all_childs(self);
+ }
+ /* show update expired password window */
+ self->dragging = 0;
+ xrdp_newpass_wnd_create(self);
+ xrdp_bitmap_invalidate(self->screen, 0);
+ xrdp_wm_set_focused(self, self->newpass_window);
+ xrdp_wm_set_login_mode(self, 21);
+ }
+ else if (self->login_mode == 22)
+ {
+ /* do change expired password session */
+ xrdp_wm_delete_all_childs(self);
+ self->dragging = 0;
+ if (xrdp_mm_change_expired_password(self->mm) == 0)
+ {
+ xrdp_wm_set_login_mode(self, 2); /* with password updated, connect again */
+ }
+ else
+ {
+ xrdp_wm_set_login_mode(self, 20); /* try to change password again */
+ }
+ }
return 0;
}
@@ -1830,11 +1858,19 @@ xrdp_wm_log_wnd_notify(struct xrdp_bitmap *wnd,
xrdp_bitmap_invalidate(wm->screen, &rect);
/* if module is gone, reset the session when ok is clicked */
+ /* unless we are to update password */
if (wm->mm->mod_handle == 0)
{
/* make sure autologin is off */
wm->session->client_info->rdp_autologin = 0;
- xrdp_wm_set_login_mode(wm, 0); /* reset session */
+ if (wm->login_mode == 21)
+ {
+ xrdp_wm_set_login_mode(wm, 20); /* try update password again */
+ }
+ else
+ {
+ xrdp_wm_set_login_mode(wm, 0); /* reset session */
+ }
}
}
}
@@ -1893,6 +1929,9 @@ xrdp_wm_show_log(struct xrdp_wm *self)
return 0;
}
+ /* delete all dialogs, they will be created when needed anyway */
+ xrdp_wm_delete_all_childs(self);
+
if (self->log_wnd == 0)
{
w = DEFAULT_WND_LOG_W;
--
2.6.6