/*******************************************************
* setpass *
* sets AIX passwords in batch mode *
* options *
* -u <username> Username of password to set *
* -t <timestamp> last amended time - defaults to *
* current time *
* -p <password> password in plain text *
* -e <encrypted password> encrypted password *
* -a enforce password change *
* The -e and -p optins are mutually exclusive *
*******************************************************/
#include <stdio.h>
#include <usersec.h>
#include <userpw.h>
#include <pwd.h>
#include <crypt.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#define nogood(c) ((! isupper(c))&&(!isdigit(c))&&(c!='.')&&(c!='/'))
char *myencrypt ( char *pword )
{
char salt[2];
time_t T;
int i;
T = time ( &T );
srandom ( ( time (&T) % 32786 ) + getpid() );
for ( i = 0; i < 2; i++ )
{
do
{
salt[i] = (char)random() & 0x007F;
}
while ( nogood ( salt[i] ) );
}
return ( crypt ( pword, salt ) );
}
void print_usage ( char *progname, char *message, int exit_value )
{
fprintf ( stderr, "%s\nUsage:- %s \n\t-u <username> \n\t-p <plain text password string> | -e <encrypted password string> \n\t[-t <timestamp>]\n\t[-a]\n", message, progname );
fprintf ( stderr, "\tIf the -t flag is not set current time is used\n" );
fprintf ( stderr, "\t-a flag enforces password change at next login\n" );
exit (exit_value);
}
extern int errno;
extern char *optarg;
main(int argc, char *argv[])
{
struct passwd pw;
struct userpw *upw;
char **msgp;
time_t T;
int c;
int nUID;
int iAflag = 0;
char *uname = NULL;
char *pword = NULL;
char *cpword = NULL;
char *tstamp = NULL;
if ( getuid() != 0 )
print_usage ( argv[0], "You must be root to use this", 1 );
while ( ( c = getopt ( argc, argv, "u:p:t:e:a" ) ) != EOF )
{
switch (c)
{
case 'u' :
uname = optarg;
break;
case 'e' :
pword = optarg;
break;
case 'p' :
cpword = optarg;
break;
case 't' :
tstamp = optarg;
break;
case 'a' :
iAflag = 1;
break;
case '?' :
print_usage ( argv[0], "Unknown option", 1 );
break;
}
}
if ( ! uname )
print_usage ( argv[0], "No user name specified", 1 );
if ( ( ! pword ) && ( ! tstamp ) && ( ! cpword ) )
print_usage ( argv[0], "At least one of password or timestamp must be specified", 1 );
if ( pword && cpword )
print_usage ( argv[0], "Either clear password OR encrypted password may be used", 1 );
if ((setuserdb (S_WRITE)) != 0)
print_usage ( argv[0], "Unable to open /etc/passwd for writing", 1 );
if ((setpwdb (S_WRITE)) != 0)
print_usage ( argv[0], "Unable to open /etc/security/passwd for writing", 1 );
if ((getuserattr ( uname, S_ID, &nUID, SEC_INT )) != 0 )
{
if (errno == ENOENT)
print_usage ( argv[0], "No entry for this user", 1 );
else
print_usage ( argv[0], "Unknown error editing /etc/passwd", 1 );
}
/*
if ( nUID < 1000 )
{
print_usage ( argv[0], "This facility is only valid for non privileged users", 1 );
}
*/
if ((putuserattr ( uname, S_PWD, "!", SEC_CHAR)) != 0)
{
if (errno == ENOENT)
print_usage ( argv[0], "No entry for this user", 1 );
else
print_usage ( argv[0], "Unknown error editing /etc/passwd", 1 );
}
if ((putuserattr ( uname, S_ID, "0", SEC_COMMIT)) != 0)
print_usage ( argv[0], "Unable to commit chages to /etc/passwd", 1 );
if ( ( upw = getuserpw ( uname ) ) == NULL )
print_usage ( argv[0], "Unable to get user details", 1 );
if ( pword )
upw->upw_passwd = pword;
if ( cpword )
upw->upw_passwd = myencrypt ( cpword );
if ( tstamp )
upw->upw_lastupdate = (time_t) atol ( tstamp );
else
upw->upw_lastupdate = (time_t ) time ( &T );
if ( iAflag )
upw->upw_flags = PW_ADMCHG;
if ((putuserpwhist ( upw, msgp)) != 0)
print_usage ( argv[0], "Unable to update /etc/security/passwd", 1 );
if ((enduserdb ()) != 0)
print_usage ( argv[0], "Unable to close /etc/passwd", 1 );
if ((endpwdb ()) != 0)
print_usage ( argv[0], "Unable to close /etc/security/passwd", 1 );
}