Skip to content

Commit

Permalink
Now invocation of Haiku users in Haiku users list opens a dialog box …
Browse files Browse the repository at this point in the history
…with that user's information, and allows to change its password.
  • Loading branch information
cafeina committed Aug 3, 2024
1 parent 23579d1 commit 88a2490
Show file tree
Hide file tree
Showing 11 changed files with 357 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/application/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ SRCS = mApp.cpp \
mBitmap.cpp \
mWindow.cpp \
mClockView.cpp \
mLoginBox.cpp \
mSystemInfo.cpp \
mBackgroundView.cpp \
mSessionBar.cpp \
mLogger.cpp \
mSysLogin.cpp \
../common/mLoginBox.cpp \
../common/ThreadedClass.cpp \
../common/LockWorkstationConfig.cpp

Expand Down
2 changes: 1 addition & 1 deletion src/application/mWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "mWindow.h"
#include "mBackgroundView.h"
#include "mSessionBar.h"
#include "mSysLogin.h"
#include "../common/mSysLogin.h"
#include "../common/LockWorkstationConfig.h"

const char* mDefaultPathToSelBG = "/login_gfx";
Expand Down
70 changes: 70 additions & 0 deletions src/common/AuthenticationUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@
* Copyright 2024, cafeina <cafeina@world>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include <private/app/RegistrarDefs.h>
#include <private/kernel/util/KMessage.h>
#include <private/libroot/user_group.h>
#include <private/shared/AutoLocker.h>
#include <ctime>
#include <string>
#include <pwd.h>
#include <shadow.h>
#include <unistd.h>
#include "AuthenticationUtils.h"

BStringList get_system_users(bool excludeSvcAccounts)
Expand All @@ -30,3 +37,66 @@ BStringList get_system_users(bool excludeSvcAccounts)
endpwent();
return userlist;
}

status_t try_change_pwd(const char* name, const char* oldPassword, const char* newPassword)
{
if(name == NULL)
return B_BAD_VALUE;

struct passwd* fUserEntry = getpwnam(name);
if(fUserEntry == NULL)
return B_ENTRY_NOT_FOUND;
struct spwd* fUserShadowEntry = getspnam(name);

if(try_login(name, oldPassword) != B_OK)
return B_PERMISSION_DENIED;

KMessage kmsg(BPrivate::B_REG_UPDATE_USER);
kmsg.AddInt32("uid", fUserEntry->pw_uid);
kmsg.AddInt32("gid", fUserEntry->pw_gid);
kmsg.AddString("name", fUserEntry->pw_name);
kmsg.AddString("password", "x");
kmsg.AddString("home", fUserEntry->pw_dir);
kmsg.AddString("shell", fUserEntry->pw_shell);
kmsg.AddString("real name", fUserEntry->pw_gecos);
if(fUserShadowEntry != NULL) {
kmsg.AddInt32("min", fUserShadowEntry->sp_min);
kmsg.AddInt32("max", fUserShadowEntry->sp_max);
kmsg.AddInt32("warn", fUserShadowEntry->sp_warn);
kmsg.AddInt32("inactive", fUserShadowEntry->sp_inact);
kmsg.AddInt32("expiration", fUserShadowEntry->sp_expire);
kmsg.AddInt32("flags", fUserShadowEntry->sp_flag);
}
else {
kmsg.AddInt32("min", 0); // instant access to password change
kmsg.AddInt32("max", 0);
kmsg.AddInt32("warn", 0);
kmsg.AddInt32("inactive", 0);
kmsg.AddInt32("expiration", 99999); // In almost 274 years
kmsg.AddInt32("flags", 0);
}
const char* encrypted;
if(strcmp(newPassword, "") == 0)
encrypted = "";
else
encrypted = crypt(newPassword, std::to_string(std::rand()).c_str());
kmsg.AddString("shadow password", encrypted);
long today = static_cast<long>(std::time(nullptr));
kmsg.AddInt32("last changed", today);

KMessage kreply;

BPrivate::user_group_lock();
BPrivate::send_authentication_request_to_registrar(kmsg, kreply);
BPrivate::user_group_unlock();

return kreply.What();
}

bool system_has_user(const char* name)
{
if(name == NULL)
return false;

return getpwnam(name) != NULL;
}
3 changes: 3 additions & 0 deletions src/common/AuthenticationUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
#define _AuthenticationUtils_h_

#include <StringList.h>
#include "mSysLogin.h"

BStringList get_system_users(bool excludeSvcAccounts = true);
bool system_has_user(const char* name = NULL);
status_t try_change_pwd(const char* name = NULL, const char* oldPassword = "", const char* newPassword = "");

#endif /* _AuthenticationUtils_h_ */
File renamed without changes.
File renamed without changes.
9 changes: 8 additions & 1 deletion src/preflet/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ APP_MIME_SIG = application/x-vnd.LockWorkstation-Pref
SRCS = mApp.cpp \
mBitmap.cpp \
mWindow.cpp \
mUserInfo.cpp \
../common/AuthenticationUtils.cpp \
../common/LockWorkstationConfig.cpp \
../common/mSysLogin.cpp \
../common/ThreadedClass.cpp

# Specify the resource definition files to use. Full or relative paths can be
Expand Down Expand Up @@ -71,7 +73,12 @@ LIBPATHS =
# Additional paths to look for system headers. These use the form
# "#include <header>". Directories that contain the files in SRCS are
# NOT auto-included here.
SYSTEM_INCLUDE_PATHS = $(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/interface)
SYSTEM_INCLUDE_PATHS = \
$(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/app) \
$(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/interface) \
$(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/kernel) \
$(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/libroot) \
$(shell findpaths -e B_FIND_PATH_HEADERS_DIRECTORY private/shared)

# Additional paths paths to look for local headers. These use the form
# #include "header". Directories that contain the files in SRCS are
Expand Down
201 changes: 201 additions & 0 deletions src/preflet/mUserInfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
/*
* Copyright 2024, cafeina <cafeina@world>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#include <Catalog.h>
#include <string>
#include "mUserInfo.h"
#include "../common/AuthenticationUtils.h"

#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "mUserInfo dialog"

mUserInfo::mUserInfo(BRect frame, BWindow* parent, const char* name)
: BWindow(frame, B_TRANSLATE("User info: <invalid user>"),
B_FLOATING_WINDOW, B_ASYNCHRONOUS_CONTROLS),
fParentWindow(parent)
{
float maxwidth, maxheight;
GetSizeLimits(NULL, &maxwidth, NULL, &maxheight);
SetSizeLimits(500.0f, maxwidth, 400.0f, maxheight);

fTcUserName = new BTextControl(B_TRANSLATE("Username"), "", NULL);
fTcUserName->TextView()->MakeEditable(false);
fTcUserName->TextView()->MakeSelectable(false);
fTcUserId = new BTextControl(B_TRANSLATE("User ID"), "", NULL);
fTcUserId->TextView()->MakeEditable(false);
fTcUserId->TextView()->MakeSelectable(false);
fTcGroupId = new BTextControl(B_TRANSLATE("Group ID"), "", NULL);
fTcGroupId->TextView()->MakeEditable(false);
fTcGroupId->TextView()->MakeSelectable(false);
fTcGecos = new BTextControl(B_TRANSLATE("User information"), "", NULL);
fTcGecos->TextView()->MakeEditable(false);
fTcGecos->TextView()->MakeSelectable(false);
fTcHomeDir = new BTextControl(B_TRANSLATE("Home directory"), "", NULL);
fTcHomeDir->TextView()->MakeEditable(false);
fTcHomeDir->TextView()->MakeSelectable(false);
fTcLoginShell = new BTextControl(B_TRANSLATE("Login shell"), "", NULL);
fTcLoginShell->TextView()->MakeEditable(false);
fTcLoginShell->TextView()->MakeSelectable(false);

fTcOldPassword = new BTextControl(B_TRANSLATE("Current password"), "",
NULL);
fTcOldPassword->TextView()->HideTyping(true);
fTcNewPassword = new BTextControl(B_TRANSLATE("New password"), "",
new BMessage(UI_PWD_TEXT_MODIFIED));
fTcNewPassword->TextView()->HideTyping(true);
fTcNewPassword->SetModificationMessage(new BMessage(UI_PWD_TEXT_MODIFIED));
fTcConfirmNewPassword = new BTextControl(B_TRANSLATE("Confirm new password"),
"", new BMessage(UI_PWD_TEXT_MODIFIED));
fTcConfirmNewPassword->TextView()->HideTyping(true);
fTcConfirmNewPassword->SetModificationMessage(new BMessage(UI_PWD_TEXT_MODIFIED));
fBtChangePwd = new BButton("bt_go", B_TRANSLATE("Change password"),
new BMessage(UI_PWD_CHANGE_REQUESTED));

containerView = new BView("v_pwdc", B_SUPPORTS_LAYOUT, NULL);
containerView->SetViewUIColor(B_TOOL_TIP_BACKGROUND_COLOR);
BLayoutBuilder::Group<>(containerView, B_VERTICAL, 0)
.SetInsets(B_USE_SMALL_INSETS)
.AddGrid(B_USE_SMALL_SPACING, B_USE_SMALL_SPACING)
.SetInsets(0, 0, 0, B_USE_SMALL_INSETS)
.AddTextControl(fTcOldPassword, 0, 0)
.AddTextControl(fTcNewPassword, 0, 1)
.AddTextControl(fTcConfirmNewPassword, 0, 2)
.End()
.AddGroup(B_HORIZONTAL)
.AddGlue()
.Add(fBtChangePwd)
.End()
.End();
containerView->Hide();

fBtShowPwdChangeView = new BButton("bt_change", B_TRANSLATE("Change pass"),
new BMessage(UI_WINDOW_SHOW_PWDCHANGE));
fBtShowPwdChangeView->SetBehavior(BButton::B_TOGGLE_BEHAVIOR);
fBtCloseWindow = new BButton("bt_ok", B_TRANSLATE("Cerrar"),
new BMessage(UI_WINDOW_CLOSE));

BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
.SetInsets(B_USE_SMALL_INSETS)
.AddGrid(B_USE_SMALL_SPACING, B_USE_SMALL_SPACING)
.SetInsets(0, 0, 0, B_USE_SMALL_INSETS)
.AddTextControl(fTcUserName, 0, 0)
.AddTextControl(fTcUserId, 0, 1)
.AddTextControl(fTcGroupId, 0, 2)
.AddTextControl(fTcGecos, 0, 3)
.AddTextControl(fTcHomeDir, 0, 4)
.AddTextControl(fTcLoginShell, 0, 5)
.End()
.AddGlue()
.AddGroup(B_HORIZONTAL)
.SetInsets(0, 0, 0, B_USE_SMALL_INSETS)
.Add(containerView)
.End()
.AddGlue()
.AddGroup(B_HORIZONTAL)
.Add(fBtShowPwdChangeView)
.AddGlue()
.Add(fBtCloseWindow)
.End()
.End();

_InitUIData(name);

CenterIn(fParentWindow->Frame());
}

void mUserInfo::MessageReceived(BMessage* message)
{
switch(message->what)
{
case UICmds::UI_PWD_TEXT_MODIFIED:
{
bool result = _NewPasswordIsOK();
fTcNewPassword->MarkAsInvalid(!result);
fTcConfirmNewPassword->MarkAsInvalid(!result);
fBtChangePwd->SetEnabled(result);
break;
}
case UICmds::UI_PWD_CHANGE_REQUESTED:
{
if(!_NewPasswordIsOK()) {
Alert(B_TRANSLATE("Warning"), B_TRANSLATE("New passwords do not match."),
B_WARNING_ALERT);
break;
}

status_t status = try_change_pwd(fUserEntry->pw_name,
fTcOldPassword->Text(), fTcConfirmNewPassword->Text());
switch(status) {
case B_PERMISSION_DENIED:
Alert(B_TRANSLATE("Error"), B_TRANSLATE("Authentication failed."),
B_STOP_ALERT);
break;
case B_OK:
Alert(B_TRANSLATE("Good"),
B_TRANSLATE("Password was changed successfully."), B_INFO_ALERT);
Quit();
break;
case B_BAD_VALUE:
Alert(B_TRANSLATE("Error"),
B_TRANSLATE("Bad data: username cannot be empty."),
B_STOP_ALERT);
break;
default:
Alert(B_TRANSLATE("Error"),
B_TRANSLATE("Password could not be changed."), B_STOP_ALERT);
break;
}
break;
}
case UICmds::UI_WINDOW_SHOW_PWDCHANGE:
{
if(containerView->IsHidden()) {
containerView->Show();
fTcOldPassword->SetEnabled(true);
fTcNewPassword->SetEnabled(true);
fTcConfirmNewPassword->SetEnabled(true);
fBtChangePwd->SetEnabled(_NewPasswordIsOK());
}
else {
containerView->Hide();
fTcOldPassword->SetEnabled(false);
fTcNewPassword->SetEnabled(false);
fTcConfirmNewPassword->SetEnabled(false);
fBtChangePwd->SetEnabled(false);
}
ResizeToPreferred();
break;
}
case UICmds::UI_WINDOW_CLOSE:
Quit();
break;
default:
BWindow::MessageReceived(message);
break;
}
}

void mUserInfo::_InitUIData(const char* username)
{
fUserEntry = getpwnam(username);
if(fUserEntry == NULL)
return;
fUserShadowEntry = getspnam(username);

BString str;
str.SetToFormat(B_TRANSLATE("User info: %s"), username);
SetTitle(str.String());

fTcUserName->SetText(fUserEntry->pw_name);
fTcUserId->SetText(std::to_string(fUserEntry->pw_uid).c_str());
fTcGroupId->SetText(std::to_string(fUserEntry->pw_gid).c_str());
fTcGecos->SetText(fUserEntry->pw_gecos);
fTcHomeDir->SetText(fUserEntry->pw_dir);
fTcLoginShell->SetText(fUserEntry->pw_shell);
}

bool mUserInfo::_NewPasswordIsOK()
{
return strcmp(fTcNewPassword->Text(), fTcConfirmNewPassword->Text()) == 0;
}
54 changes: 54 additions & 0 deletions src/preflet/mUserInfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright 2024, cafeina <cafeina@world>
* All rights reserved. Distributed under the terms of the MIT license.
*/
#ifndef _mUserInfo_h_
#define _mUserInfo_h_

#include <InterfaceKit.h>
#include <SupportKit.h>
#include <pwd.h>
#include <shadow.h>

enum UICmds {
UI_WINDOW_CLOSE = 'clse',
UI_WINDOW_SHOW_PWDCHANGE = 'pwdc',
UI_PWD_TEXT_MODIFIED = 'modf',
UI_PWD_CHANGE_REQUESTED = 'chng'
};

inline int32 Alert(const char* title, const char* text, alert_type type = B_INFO_ALERT) {
BAlert* alert = new BAlert(title, text, "OK");
alert->SetType(type);
return alert->Go();
}

class mUserInfo : public BWindow
{
public:
mUserInfo(BRect frame, BWindow* parent, const char* name);
virtual void MessageReceived(BMessage* message);
private:
void _InitUIData(const char* username);
status_t _RequestChange();
bool _NewPasswordIsOK();
private:
struct passwd *fUserEntry;
struct spwd *fUserShadowEntry;
BWindow *fParentWindow;
BView *containerView;
BButton *fBtChangePwd,
*fBtShowPwdChangeView,
*fBtCloseWindow;
BTextControl *fTcUserName,
*fTcUserId,
*fTcGecos,
*fTcGroupId,
*fTcHomeDir,
*fTcLoginShell,
*fTcOldPassword,
*fTcNewPassword,
*fTcConfirmNewPassword;
};

#endif /* _mUserInfo_h_ */
Loading

0 comments on commit 88a2490

Please sign in to comment.