Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:42.3:Update
xrdp
xrdp-fate318398-change-expired-password.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xrdp-fate318398-change-expired-password.patch of Package xrdp
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
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor