#include #include #include "usersbygroup.h" #include "usersbygroup.m" #include #include #include static HELP_FILE help_usersbg ("usersbygroup","intro"); static HELP_FILE help_mng ("usersbygroup","manage"); static HELP_FILE help_task ("usersbygroup","task"); static REGISTER_PRIVI_HELP p (help_usersbg ,P_MSG_U(T_MODPRIVI,"Privileges: Usersbygroup module")); static const char K_USERSBG[]="usersbg"; static const char K_USERSBGSHELL[]="usersbg_shell"; static const char K_USERSBGCMD[]="usersbg_cmd"; static const char K_USERSBGTITLE[]="usersbg_title"; static const char K_INDEX[]="index"; static const char K_USERSBGMAYADD[]="mayadd"; class USERSBG_CMD: public ARRAY_OBJ{ public: SSTRING cmd; SSTRING title; /*~PROTOBEG~ USERSBG_CMD */ public: USERSBG_CMD (const char *_cmd, const char *_title); /*~PROTOEND~ USERSBG_CMD */ }; PUBLIC USERSBG_CMD::USERSBG_CMD(const char *_cmd, const char *_title) { cmd.setfrom (_cmd); title.setfrom (_title); } class USERSBG_CMDS: public ARRAY{ /*~PROTOBEG~ USERSBG_CMDS */ public: USERSBG_CMD *getitem (int no)const; /*~PROTOEND~ USERSBG_CMDS */ }; PUBLIC USERSBG_CMD *USERSBG_CMDS::getitem (int no) const { return (USERSBG_CMD*)ARRAY::getitem(no); } class USERSBG: public ARRAY_OBJ{ public: SSTRING group; SSTRING shell; USERSBG_CMDS cmds; bool mayadd; /*~PROTOBEG~ USERSBG */ public: USERSBG (const char *_group); USERSBG (void); void dispatchcmd (PRIVILEGE *priv, USERSBG_CMD *cmd); int edit (void); PRIVILEGE *getpriv (void); PRIVILEGE *getpriv_add (void); private: USER *getrefuser (void); public: void manage (void); void mngaccounts (PRIVILEGE *privi); /*~PROTOEND~ USERSBG */ }; PUBLIC USERSBG::USERSBG (const char *_group) { if (_group != NULL){ group.setfrom (_group); shell.setfrom (linuxconf_getval (K_USERSBGSHELL,_group,"/bin/false")); mayadd = linuxconf_getvalnum(K_USERSBGMAYADD,_group,1); SSTRINGS commands,titles; linuxconf_getall (K_USERSBGCMD,_group,commands,false); linuxconf_getall (K_USERSBGTITLE,_group,titles,false); for (int i=0; iget(); SSTRING *t = titles.getitem(i); const char *title = t == NULL ? command : t->get(); cmds.add (new USERSBG_CMD (command,title)); } } } PUBLIC USERSBG::USERSBG () { } PUBLIC int USERSBG::edit() { DIALOG dia; FIELD_COMBO *comb = dia.newf_combo (MSG_U(F_GROUP,"Group"),group); GROUPS groups; groups.sortbyname(); for (int i=0; iaddopt (groups.getitem(i)->getname()); } dia.newf_str (MSG_U(F_SHELL,"Shell"),shell); dia.last_noempty(); dia.newf_chk (MSG_U(F_MAYADD,"May add"),mayadd,MSG_U(I_MAYADD,"new accounts")); dia.last_noempty(); dia.newf_title ("",MSG_U(T_COMMANDS,"Administration commands")); // Make sure there is 3 empty slots to add new commands int nbempty = 0; for (int i=0; icmd.is_empty()) nbempty++; } for (int i=nbempty; i<3; i++) cmds.add (new USERSBG_CMD("","")); for (int i=0; icmd); combo->addopt ("/usr/lib/linuxconf/usersbygroup/reset-kde.sh"); combo->addopt ("/usr/lib/linuxconf/usersbygroup/install-bookmarks.sh"); dia.newf_str (MSG_U(F_TITLE,"Title"),c->title); } int ret = -1; int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_GROUPDEF,"Group configuration") ,"",help_usersbg,nof,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_DEL); if (code == MENU_CANCEL || code == MENU_ESCAPE){ dia.restore(); break; }else if (code == MENU_DEL){ if (xconf_delok()){ ret = 1; break; } }else if (groups.getitem(group.get())==NULL){ xconf_error (MSG_U(E_UNKNOWNGRP,"Unknown group %s"),group.get()); nof = 0; }else{ ret = 0; break; } } return ret; } class USERSBGS: public ARRAY{ /*~PROTOBEG~ USERSBGS */ public: USERSBGS (void); private: void addone (const char *g); public: void config (void); USERSBG *getitem (int no)const; void locate (const char *group, bool setting); void menu (void); void setupdia (DIALOG_RECORDS&dia, USERSBGS&visible); int write (void); /*~PROTOEND~ USERSBGS */ }; PUBLIC USERSBG *USERSBGS::getitem (int no) const { return (USERSBG*)ARRAY::getitem(no); } PUBLIC USERSBGS::USERSBGS() { SSTRINGS tb; linuxconf_getall (K_USERSBG,K_INDEX,tb,false); for (int i=0; iget())); } } PUBLIC int USERSBGS::write() { linuxconf_removeall (K_USERSBG,K_INDEX); for (int i=0; igroup.get(); linuxconf_add (K_USERSBG,K_INDEX,group); linuxconf_replace (K_USERSBGSHELL,group,b->shell); linuxconf_replace (K_USERSBGMAYADD,group,b->mayadd); linuxconf_removeall (K_USERSBGCMD,group); linuxconf_removeall (K_USERSBGTITLE,group); for (int j=0; jcmds.getnb(); j++){ USERSBG_CMD *c = b->cmds.getitem(j); if (!c->cmd.is_empty()){ linuxconf_add (K_USERSBGCMD,group,c->cmd.get()); linuxconf_add (K_USERSBGTITLE,group,c->title.get()); } } } return linuxconf_save(); } static PRIVILEGES tb; static bool privi_changed = false; static void usersbg_setprivi() { if (tb.getnb()==0 || privi_changed){ privi_changed = false; tb.remove_all(); USERSBGS us; int n = us.getnb(); const char *section = userconf_getprivsection(); for (int i=0; igroup.get(); char id[PATH_MAX]; sprintf (id,"usersbg_%s",group); char title[100]; snprintf (title,sizeof(title)-1,MSG_U(I_PRIVGROUP,"%s group"),group); tb.add (new PRIVILEGE (id,title,section)); sprintf (id,"usersbgadd_%s",group); snprintf (title,sizeof(title)-1,MSG_U(I_PRIVGROUPADD,"%s group (add accounts)"),group); tb.add (new PRIVILEGE (id,title,section)); } } } static PRIVILEGE_DECLARATOR usersbg_decl(usersbg_setprivi); static int cmp_by_name (const ARRAY_OBJ *o1, const ARRAY_OBJ *o2) { USERSBG *b1 = (USERSBG*)o1; USERSBG *b2 = (USERSBG*)o2; return b1->group.cmp(b2->group); } PUBLIC void USERSBGS::setupdia (DIALOG_RECORDS &dia, USERSBGS &visible) { visible.neverdelete(); visible.remove_all(); usersbg_setprivi(); sort (cmp_by_name); if (dia.getnb()==0) dia.newf_head ("",MSG_U(H_GROUPS,"Group\tShell")); for (int i=0; igetpriv(); if (perm_checkpriv(priv)){ dia.set_menuitem (i,b->group.get(),b->shell.get()); visible.add (b); } } dia.remove_last (getnb()+1); } /* Return a standard user account for that special group. */ PRIVATE USER *USERSBG::getrefuser() { USER *ret = NULL; int gid = group_getcreate(group.get() ,MSG_U(P_GROUP,"setup special account")); if (gid != -1){ ret = new USER (NULL,NULL,-1,gid,NULL,"",shell.get()); } return ret; } class USERARRAY: public ARRAY{ /*~PROTOBEG~ USERARRAY */ public: USER *getitem (int no)const; /*~PROTOEND~ USERARRAY */ }; PUBLIC USER *USERARRAY::getitem (int no) const { return (USER*)ARRAY::getitem(no); } /* Let the co-admin apply a command to a selection of users */ PUBLIC void USERSBG::dispatchcmd(PRIVILEGE *priv, USERSBG_CMD *cmd) { USER *like = getrefuser(); if (like != NULL){ bool intro_done = false; USERS users; // Lookup all users like the reference user USERARRAY arr; arr.neverdelete(); int nb = users.getnb(); for (int i=0; iis_like(like)){ arr.add (u); } } // Set the dialog DIALOG dia; nb = arr.getnb(); char tbsel[nb]; memset (tbsel,0,sizeof(tbsel)); int nof = 0; while (1){ if (dia.getnb()==0){ for (int i=0; igetname(),tbsel[i],u->getgecos()); } dia.setbutinfo (MENU_USR1,MSG_U(B_UNSELALL,"None"),MSG_R(B_UNSELALL)); dia.setbutinfo (MENU_USR2,MSG_U(B_SELALL,"All"),MSG_R(B_SELALL)); } MENU_STATUS code = dia.edit (cmd->title.get() ,MSG_U(I_SETTINGTASK ,"You must select the user account on which\n" "you want to apply the administration tasks") ,help_task ,nof,MENUBUT_CANCEL|MENUBUT_ACCEPT|MENUBUT_USR1|MENUBUT_USR2); if (code == MENU_CANCEL || code == MENU_ESCAPE){ break; }else if (code == MENU_USR1){ memset (tbsel,0,sizeof(tbsel)); dia.remove_all(); }else if (code == MENU_USR2){ memset (tbsel,1,sizeof(tbsel)); dia.remove_all(); }else if (code == MENU_ACCEPT){ /* #Specification: admin task / command line format The admin command is called with argument. The user account list is appended after a -- sequence. All arguments before the -- are the one specified by the super-user when he created the task. */ SSTRING s; s.setfrom (cmd->cmd.get()); s.append (" --"); bool one = false; for (int i=0; igetname()); one = true; } } if (!one){ xconf_notice (MSG_U(N_NONESELECTED ,"No account selected\n" "Nothing to do !")); }else{ PRIVILEGE *old = perm_setdefprivi (priv); if (!intro_done){ intro_done = true; net_introlog (NETINTRO_MISC); } netconf_system (30,s.get()); perm_setdefprivi (old); xconf_notice (MSG_U(N_DONE,"Done")); } } } } } /* Normal account management (creation/deletion/password...) */ PUBLIC void USERSBG::mngaccounts(PRIVILEGE *privi) { USER *like = getrefuser(); if (like != NULL){ USERS users; bool may = mayadd; if (may){ // Check the privilege PRIVILEGE *padd = getpriv_add(); if (!perm_checkpriv(padd)) may = false; } users.setmayadd (may); users.edit(like,privi,0); delete like; } } /* Returns the PRIVILEGE object associated with this special group */ PUBLIC PRIVILEGE *USERSBG::getpriv() { char id[PATH_MAX]; sprintf (id,"usersbg_%s",group.get()); return privilege_lookup (id); } /* Returns the PRIVILEGE object associated with this special group, controlling if the co-admin is allowed to add new acccounts */ PUBLIC PRIVILEGE *USERSBG::getpriv_add() { char id[PATH_MAX]; sprintf (id,"usersbgadd_%s",group.get()); return privilege_lookup (id); } PUBLIC void USERSBG::manage() { usersbg_setprivi(); PRIVILEGE *priv = getpriv(); if (perm_access (priv,MSG_U(P_MNGSPCGRP,"manage a group"))){ if (cmds.getnb()==0){ mngaccounts(priv); }else{ // Ok, there are administration tasks define. Lets create // a menu DIALOG_MENU dia; dia.new_menuitem (MSG_U(M_MANAGE,"Manage") ,MSG_U(M_ACCOUNTS,"accounts")); for (int i=0; ititle.get()); } int nof = 0; while (1){ char title[100]; snprintf (title,sizeof(title)-1 ,MSG_U(T_MNGSPC,"Manage group %s"),group.get()); MENU_STATUS code = dia.editmenu (title ,"",help_mng ,nof,0); if (code == MENU_QUIT || code == MENU_ESCAPE){ break; }else if (nof == 0){ mngaccounts (priv); }else{ dispatchcmd (priv,cmds.getitem(nof-1)); } } } } } PUBLIC void USERSBGS::menu() { DIALOG_RECORDS dia; USERSBGS visible; setupdia (dia,visible); int nof = 0; while (1){ MENU_STATUS code = dia.editmenu (MSG_U(T_GROUPS,"Special groups") ,MSG_U(I_GROUPS,"You can manage special groups:\n" " -Add/Remove user accounts\n" " -Set and change account's password\n" " -Perform some tasks defined by the super-user") ,help_usersbg ,nof,0); if (code == MENU_QUIT || code == MENU_ESCAPE){ break; }else if (nof >=0 && nof < getnb()){ USERSBG *b = visible.getitem(nof); b->manage(); } } } PRIVATE void USERSBGS::addone(const char *g) { USERSBG *b = new USERSBG(g); int code = b->edit(); if (code == 0){ add (b); write(); privi_changed = true; }else{ delete b; } } PUBLIC void USERSBGS::config() { DIALOG_RECORDS dia; dia.addwhat (MSG_U(I_ADD,"Select [Add] to add a new special group config")); int nof = 0; while (1){ USERSBGS visible; setupdia (dia,visible); MENU_STATUS code = dia.editmenu (MSG_R(T_GROUPS) ,MSG_U(I_CONFGROUPS,"You can configure special groups") ,help_usersbg ,nof,0); if (code == MENU_QUIT || code == MENU_ESCAPE){ break; }else if (code == MENU_ADD){ addone(NULL); }else if (nof >=0 && nof < getnb()){ USERSBG *b = visible.getitem(nof); int code = b->edit(); if (code != -1){ if (code == 1) remove_del (b); write (); privi_changed = true; } } } } void usersbg_edit() { USERSBGS us; us.menu(); } void usersbg_config() { USERSBGS us; us.config(); } PUBLIC void USERSBGS::locate (const char *group, bool setting) { bool found = false; for (int i=0; igroup.cmp(group)==0){ if (u->edit()==0) write(); found = true; break; } } if (!found && setting){ addone(group); } } static void usersbg_locate (const char *group, bool setting) { USERSBGS us; us.locate (group,setting); } static void usersbg_list (SSTRINGS &tb) { USERSBGS us; for (int i=0; igroup.get())); } } /* Show the special url used to access the html mode of linuxconf */ void usersbg_listspc () { USERSBGS us; if (us.getnb() > 0){ html_printf ("

\n"); html_printf ("

%s
\n" ,MSG_U(I_MNGUSERS,"Manage users by group")); html_printf ("

\n"); } } #include static PUBLISH_VARIABLES_MSG usersbg_var_list[]={ {"group",P_MSG_R(F_GROUP)}, {"shell",P_MSG_R(F_SHELL)}, {"command",P_MSG_R(F_COMMAND)}, {"title",P_MSG_R(F_TITLE)}, {"mayadd",P_MSG_R(F_MAYADD)}, { NULL, NULL } }; static REGISTER_VARIABLES usersbg_registry1("usersbygroup","groups",usersbg_var_list ,NULL,usersbg_locate,usersbg_list);