#include #include #include #include #include #include #include #include "internal.h" #include "userconf.h" #include "../paths.h" #include "userconf.m" #include #include #include using namespace std; #define ETC_SHADOW_TMP "/etc/shadow.tmp" static USERCONF_HELP_FILE help_shadow ("shadow"); static CONFIG_FILE f_shadow (ETC_SHADOW,help_shadow ,CONFIGF_MANAGED|CONFIGF_TMPLOCK ,"root","root",0600,subsys_useraccounts); static int shadow_atoi (const char *str, int defval) { if (str != NULL && (isdigit(str[0]) || str[0] == '-')){ defval = atoi(str); } return defval; } /* Used when reading the /etc/shadow file */ PUBLIC SHADOW::SHADOW(const char *line) { char words[9][100]; user_splitline (line,words); name.setfrom (words[0]); passwd.setfrom (words[1]); last = shadow_atoi(words[2],-1); may = shadow_atoi(words[3],-1); must = shadow_atoi(words[4],99999); warn = shadow_atoi(words[5],-1); expire = shadow_atoi(words[6],-1); disable = shadow_atoi(words[7],-1); reserved.setfrom(words[8]); } static const char K_SHADOW[]="shadow"; static const char K_DEFAULT[]="default"; static int stdduration = 0; PRIVATE void SHADOW::initdef() { last = -1; may = -1; must = 99999; warn = -1; expire = -1; disable = -1; const char *str = linuxconf_getval (K_SHADOW,K_DEFAULT); if (str != NULL){ if (sscanf (str,"%d %d %d %d %d",&may,&must,&warn,&expire ,&stdduration)==5){ if (stdduration != 0){ disable = time(NULL)/(24*60*60) + stdduration; } // fprintf (stderr,"stdduration %d %d\n",stdduration,disable); } } } /* Used when creating a new record */ PUBLIC SHADOW::SHADOW() { initdef(); } PUBLIC SHADOW::SHADOW( const char *_name, const char *_passwd, const char *_last, const char *_may, const char *_must, const char *_warn, const char *_expire, const char *_disable) { name = _name; passwd = _passwd; last = shadow_atoi(_last,-1); may = shadow_atoi(_may,-1); must = shadow_atoi(_must,99999); warn = shadow_atoi(_warn,-1); expire = shadow_atoi(_expire,-1); disable = shadow_atoi(_disable,-1); } PUBLIC void SHADOW::setname (const char *_name) { name.setfrom (_name); } PUBLIC void SHADOW::setpasswd (const char *_pass) { passwd.setfrom (_pass); } /* Setup the part of the dialog for shadow default policies. */ PUBLIC void SHADOW::setdialog (DIALOG &dia) { dia.newf_title (MSG_R(T_PARAMS),1,"",MSG_R(T_PASSMNG)); static const char *tb[]={MSG_R(I_IGNORED),NULL}; static const int tbv[]={-1,0}; dia.newf_chkm_num (MSG_R(F_PASSMAY),may,tbv,tb); static const int tbv99999[]={99999,0}; dia.newf_chkm_num (MSG_R(F_PASSMUST),must,tbv99999,tb); dia.newf_chkm_num (MSG_R(F_PASSWARN),warn,tbv,tb); dia.newf_chkm_num (MSG_R(F_PASSEXPIRE),expire,tbv,tb); static const int tbv0[]={0,0}; dia.newf_chkm_num (MSG_U(F_STDDURATION,"Standard account duration") ,stdduration,tbv0,tb); } /* Save the default setting for shadow policies. */ PUBLIC int SHADOW::writedef() { linuxconf_setcursys (subsys_policies); char buf[100]; sprintf (buf,"%d %d %d %d %d",may,must,warn,expire,stdduration); linuxconf_replace (K_SHADOW,K_DEFAULT,buf); return linuxconf_save(); } /* Return the crypt password field */ PUBLIC const char *SHADOW::getpwd() const { return passwd.get(); } /* Return the number of days an account may be used after the password has expired. */ PUBLIC int SHADOW::getexpire() const { return expire; } /* Return the expiration date of the account in days since 1970 */ PUBLIC int SHADOW::getdisable() const { return disable; } /* Get the maximum number of days after which a password must be changed */ PUBLIC int SHADOW::getmustchange () const { return must; } /* Get the minimum number of days before a password may be changed (again) */ PUBLIC int SHADOW::getmaychange() const { return may; } /* Get the number of days before a password must be change, a warning should be issued */ PUBLIC int SHADOW::getwarn() const { return warn; } /* Get the date of the last password change. */ PUBLIC int SHADOW::getlastchange () const { return last; } struct SHADOWS_private{ map idx; }; /* Write one record of /etc/passwd */ PUBLIC void SHADOW::write(FILE_CFG *fout) { fprintf (fout,"%s:%s:%d:%d:%d:%d:%d:%d:%s\n" ,name.get(),passwd.get(),last,may,must,warn,expire,disable ,reserved.get()); } PUBLIC void SHADOWS::add (SHADOW *s) { priv->idx[s->name.get()] = s; ARRAY::add (s); } PUBLIC void SHADOWS::remove_del (SHADOW *s) { priv->idx.erase(s->name.get()); ARRAY::remove_del (s); } PRIVATE void SHADOWS::readusers() { FILE_CFG *fin = configf->fopen ("r"); if (fin != NULL){ char line[1000]; while (fgets(line,sizeof(line)-1,fin)!=NULL){ strip_end (line); if (line[0] != '\0'){ add (new SHADOW(line)); } } fclose (fin); } rstmodified(); } PUBLIC SHADOWS::SHADOWS() { /* #Specification: /etc/passwd / strategy /etc/shadow is read "by hand" instead of using getpwent() to avoid getting all those NIS entries. This is done when editing local user account. */ priv = new SHADOWS_private; configf = &f_shadow; readusers(); } PUBLIC SHADOWS::SHADOWS(CONFIG_FILE &_configf) { priv = new SHADOWS_private; configf = &_configf; readusers(); } PUBLIC SHADOWS::~SHADOWS() { delete priv; } /* Forget and reload the shadow information from the shadow file */ PUBLIC void SHADOWS::reload() { priv->idx.clear(); remove_all(); readusers(); } PUBLIC SHADOW *SHADOWS::getitem(int no) { return (SHADOW*)ARRAY::getitem(no); } /* Get one SHADOW specification of the table or NULL from his login name */ PUBLIC SHADOW *SHADOWS::getitem(const char *name) { SHADOW *ret = NULL; map::iterator pt = priv->idx.find(name); if (pt != priv->idx.end()){ ret = pt->second; } return ret; } PUBLIC int SHADOWS::write(PRIVILEGE *priv) { int ret = -1; FILE_CFG *fout = configf->fopen (priv,"w"); if (fout != NULL){ int nbu = getnb(); for (int i=0; iwrite(fout); } ret = configf->fclose(fout); //ret = configf->relink_tmp(); } return ret; } /* Return != 0 if the /etc/shadow file exist */ int shadow_exist () { return f_shadow.exist(); }