811536eca2
- Update to version 0.9.8 - Update xrdp-fate318398-change-expired-password.patch: Use configured values instead of hardcoded ones in login_wnd inputs - Add xrdp-support-KillDisconnected-for-Xvnc.patch: Support the KillDisconnected option for TigerVNC Xvnc sessions (boo#1101506) OBS-URL: https://build.opensuse.org/request/show/638375 OBS-URL: https://build.opensuse.org/package/show/X11:RemoteDesktop/xrdp?expand=0&rev=48
819 lines
28 KiB
Diff
819 lines
28 KiB
Diff
Index: b/sesman/auth.h
|
|
===================================================================
|
|
--- a/sesman/auth.h 2017-10-26 13:30:12.000000000 +0800
|
|
+++ b/sesman/auth.h 2018-01-04 16:40:32.178890000 +0800
|
|
@@ -106,4 +106,6 @@
|
|
int
|
|
auth_change_pwd(const char *user, const char *newpwd);
|
|
|
|
+int
|
|
+auth_change_pwd_pam(char* user, char* pass, char* newpwd);
|
|
#endif
|
|
Index: b/sesman/libscp/libscp_session.c
|
|
===================================================================
|
|
--- a/sesman/libscp/libscp_session.c 2017-10-26 13:30:12.000000000 +0800
|
|
+++ b/sesman/libscp/libscp_session.c 2018-01-04 16:40:32.178890000 +0800
|
|
@@ -75,6 +75,10 @@
|
|
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 @@
|
|
return 1;
|
|
}
|
|
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*******************************************************************/
|
|
+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;
|
|
}
|
|
|
|
Index: b/sesman/libscp/libscp_types.h
|
|
===================================================================
|
|
--- a/sesman/libscp/libscp_types.h 2017-10-04 12:44:21.000000000 +0800
|
|
+++ b/sesman/libscp/libscp_types.h 2018-01-04 16:40:32.178890000 +0800
|
|
@@ -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
|
|
@@ -77,6 +78,7 @@
|
|
char locale[18];
|
|
char* username;
|
|
char* password;
|
|
+ char* newpass;
|
|
char* hostname;
|
|
tui8 addr_type;
|
|
tui32 ipv4addr;
|
|
Index: b/sesman/libscp/libscp_v0.c
|
|
===================================================================
|
|
--- a/sesman/libscp/libscp_v0.c 2017-12-27 22:30:25.000000000 +0800
|
|
+++ b/sesman/libscp/libscp_v0.c 2018-01-04 17:09:58.859805998 +0800
|
|
@@ -329,9 +329,8 @@
|
|
}
|
|
}
|
|
}
|
|
- 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)
|
|
@@ -341,7 +340,7 @@
|
|
}
|
|
|
|
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 = g_new0(char, sz + 1);
|
|
@@ -358,6 +357,23 @@
|
|
}
|
|
g_free(buf);
|
|
|
|
+ if (code == SCP_GW_CHAUTHTOK)
|
|
+ {
|
|
+ /* reading new password */
|
|
+ in_uint16_be(c->in_s, sz);
|
|
+ buf = g_new0(char, sz + 1);
|
|
+ in_uint8a(c->in_s, buf, sz);
|
|
+ buf[sz] = '\0';
|
|
+
|
|
+ if (0 != scp_session_set_newpass(session, buf))
|
|
+ {
|
|
+ scp_session_destroy(session);
|
|
+ g_free(buf);
|
|
+ return SCP_SERVER_STATE_INTERNAL_ERR;
|
|
+ }
|
|
+ g_free(buf);
|
|
+ }
|
|
+
|
|
/* reading password */
|
|
in_uint16_be(c->in_s, sz);
|
|
buf = g_new0(char, sz + 1);
|
|
@@ -435,12 +451,13 @@
|
|
|
|
/******************************************************************************/
|
|
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);
|
|
Index: b/sesman/libscp/libscp_v0.h
|
|
===================================================================
|
|
--- a/sesman/libscp/libscp_v0.h 2017-07-19 12:23:49.000000000 +0800
|
|
+++ b/sesman/libscp/libscp_v0.h 2018-01-04 16:40:32.182893999 +0800
|
|
@@ -79,6 +79,6 @@
|
|
* @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
|
|
Index: b/sesman/scp_v0.c
|
|
===================================================================
|
|
--- a/sesman/scp_v0.c 2017-10-26 13:30:12.000000000 +0800
|
|
+++ b/sesman/scp_v0.c 2018-01-04 16:40:32.182893999 +0800
|
|
@@ -42,6 +42,13 @@
|
|
int errorcode = 0;
|
|
bool_t do_auth_end = 1;
|
|
|
|
+ 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)
|
|
@@ -53,14 +60,14 @@
|
|
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"); */
|
|
@@ -71,7 +78,7 @@
|
|
/* 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);
|
|
}
|
|
}
|
|
else if (data)
|
|
Index: b/sesman/verify_user_pam.c
|
|
===================================================================
|
|
--- a/sesman/verify_user_pam.c 2017-11-27 09:42:43.000000000 +0800
|
|
+++ b/sesman/verify_user_pam.c 2018-01-04 16:40:32.182893999 +0800
|
|
@@ -38,6 +38,7 @@
|
|
{
|
|
char user[256];
|
|
char pass[256];
|
|
+ char newpwd[256];
|
|
};
|
|
|
|
struct t_auth_info
|
|
@@ -86,6 +87,55 @@
|
|
}
|
|
|
|
/******************************************************************************/
|
|
+static int
|
|
+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
|
|
get_service_name(char *service_name)
|
|
{
|
|
@@ -103,6 +153,52 @@
|
|
}
|
|
|
|
/******************************************************************************/
|
|
+/* returns boolean */
|
|
+/* update to the new pass */
|
|
+int
|
|
+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;
|
|
+}
|
|
+
|
|
+/******************************************************************************/
|
|
/* returns long, zero is no go
|
|
Stores the detailed error code in the errorcode variable*/
|
|
|
|
Index: b/xrdp/xrdp_login_wnd.c
|
|
===================================================================
|
|
--- a/xrdp/xrdp_login_wnd.c 2017-11-27 09:42:43.000000000 +0800
|
|
+++ b/xrdp/xrdp_login_wnd.c 2018-01-04 16:40:32.182893999 +0800
|
|
@@ -187,7 +187,14 @@
|
|
{
|
|
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);
|
|
}
|
|
@@ -245,7 +252,29 @@
|
|
}
|
|
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;
|
|
@@ -545,6 +574,32 @@
|
|
return 0;
|
|
}
|
|
|
|
+/*****************************************************************************/
|
|
+/* change new password window events go here */
|
|
+static int
|
|
+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
|
|
xrdp_wm_login_fill_in_combo(struct xrdp_wm *self, struct xrdp_bitmap *b)
|
|
@@ -825,6 +880,103 @@
|
|
|
|
return 0;
|
|
}
|
|
+
|
|
+/******************************************************************************/
|
|
+int
|
|
+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(globals->ls_label_width, 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(globals->ls_input_width, 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
|
|
Index: b/xrdp/xrdp_mm.c
|
|
===================================================================
|
|
--- a/xrdp/xrdp_mm.c 2017-12-27 22:30:26.000000000 +0800
|
|
+++ b/xrdp/xrdp_mm.c 2018-01-04 16:40:32.182893999 +0800
|
|
@@ -1458,7 +1458,7 @@
|
|
/*********************************************************************/
|
|
/* return 0 on success */
|
|
static int
|
|
-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 */
|
|
@@ -1486,7 +1486,8 @@
|
|
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);
|
|
@@ -1494,6 +1495,14 @@
|
|
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 */
|
|
@@ -1523,15 +1532,19 @@
|
|
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
|
|
{
|
|
@@ -1849,7 +1862,7 @@
|
|
char port[8];
|
|
char chansrvport[256];
|
|
#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];
|
|
@@ -1889,7 +1902,7 @@
|
|
#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)
|
|
@@ -1917,45 +1930,56 @@
|
|
}
|
|
|
|
#ifndef USE_NOPAM
|
|
- if (use_pam_auth)
|
|
- {
|
|
- int reply;
|
|
- char pam_error[128];
|
|
- const char *additionalError;
|
|
- xrdp_wm_log_msg(self->wm, LOG_LEVEL_DEBUG,
|
|
- "Please wait, we now perform access control...");
|
|
+ int reply;
|
|
+ char replytxt[128];
|
|
+ char pam_error[128];
|
|
+ const char *additionalError;
|
|
+ xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "Please wait, we now perform access control...");
|
|
|
|
- /* 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);
|
|
- }
|
|
+ /* use pam either way, copy from normal user name when not explicitly inputed */
|
|
+ if (use_pam_auth_explicit == 0)
|
|
+ {
|
|
+ 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);
|
|
+ }
|
|
|
|
- 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_username, "same", 255))
|
|
+ {
|
|
+ log_message(LOG_LEVEL_DEBUG, "pamusername copied from username - same: %s", username);
|
|
+ g_strncpy(pam_auth_username, username, 255);
|
|
+ }
|
|
|
|
- /* access_control return 0 on success */
|
|
- reply = access_control(pam_auth_username, pam_auth_password, pam_auth_sessionIP);
|
|
+ if (!g_strncmp(pam_auth_password, "same", 255))
|
|
+ {
|
|
+ log_message(LOG_LEVEL_DEBUG, "pam_auth_password copied from password - same: %s", password);
|
|
+ g_strncpy(pam_auth_password, password, 255);
|
|
+ }
|
|
|
|
- xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
|
- "Reply from access control: %s",
|
|
- getPAMError(reply, pam_error, 127));
|
|
+ /* access_control return 0 on success */
|
|
+ reply = access_control(pam_auth_username, pam_auth_password, NULL, pam_auth_sessionIP, 4);
|
|
+ xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
|
|
+ "Reply from access control: %s",
|
|
+ getPAMError(reply, pam_error, 127));
|
|
|
|
- additionalError = getPAMAdditionalErrorInfo(reply, self);
|
|
- if (additionalError && additionalError[0])
|
|
- {
|
|
- xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "%s", additionalError);
|
|
- }
|
|
+ additionalError = getPAMAdditionalErrorInfo(reply, self);
|
|
+ if (additionalError && additionalError[0])
|
|
+ {
|
|
+ xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "%s", additionalError);
|
|
+ }
|
|
|
|
- if (reply != 0)
|
|
+ if (reply != 0)
|
|
+ {
|
|
+ /* show PAM errors */
|
|
+ xrdp_wm_show_log(self->wm);
|
|
+ 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
|
|
|
|
@@ -2048,6 +2072,59 @@
|
|
return rv;
|
|
}
|
|
|
|
+/*****************************************************************************/
|
|
+/* return 0 on success */
|
|
+int
|
|
+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
|
|
xrdp_mm_get_wait_objs(struct xrdp_mm *self,
|
|
Index: b/xrdp/xrdp_types.h
|
|
===================================================================
|
|
--- a/xrdp/xrdp_types.h 2017-07-19 12:23:49.000000000 +0800
|
|
+++ b/xrdp/xrdp_types.h 2018-01-04 16:40:32.182893999 +0800
|
|
@@ -325,6 +325,7 @@
|
|
struct xrdp_cache* cache;
|
|
int palette[256];
|
|
struct xrdp_bitmap* login_window;
|
|
+ struct xrdp_bitmap* newpass_window;
|
|
/* generic colors */
|
|
int black;
|
|
int grey;
|
|
Index: b/xrdp/xrdp_wm.c
|
|
===================================================================
|
|
--- a/xrdp/xrdp_wm.c 2018-01-04 16:40:31.998709999 +0800
|
|
+++ b/xrdp/xrdp_wm.c 2018-01-04 16:40:32.182893999 +0800
|
|
@@ -1896,6 +1896,34 @@
|
|
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_children(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_children(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;
|
|
}
|
|
@@ -1940,11 +1968,19 @@
|
|
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 */
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -2006,6 +2042,9 @@
|
|
return 0;
|
|
}
|
|
|
|
+ /* delete all dialogs, they will be created when needed anyway */
|
|
+ xrdp_wm_delete_all_children(self);
|
|
+
|
|
if (self->log_wnd == 0)
|
|
{
|
|
w = DEFAULT_WND_LOG_W;
|