You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

339 lines
6.9 KiB

/*
chpasswd.c
Changes local user password
Developed by
Pedro L Orso - orso@onda.com.br
Changed by
Thiago Melo de Paula - thiago@fafibe.br
Paul Lesneiwski - pdontthink@angrynerds.com
Released under GNU GPL - see http://www.gnu.org/copyleft/gpl.html
How to compile:
gcc -lcrypt -O -o chpasswd chpasswd.c; chmod 4750 chpasswd; chown root:apache chpasswd
gcc -Wall -lcrypt -O -o chpasswd chpasswd.c; chmod 4750 chpasswd; chown root:apache chpasswd
*/
#define TMPFILE "/tmp/chpasswdXXXXXX"
#define PASSWD "/etc/passwd"
#define SHADOW "/etc/shadow"
#define STR_MAX 100
#define MAXLEN 1024
#define hhex(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F'))
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <crypt.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
//#include <errno.h>
#include <sys/stat.h>
void eperror(register char *);
void getword(char *, char *, char);
void to64(register char *, register long, register int);
void putline(FILE *,char *);
void *xmalloc(size_t);
static void fixpwd(unsigned char *);
static int htoi(unsigned char *s);
int main(int argc, char *argv[]){
int ok, fdes, test = 0;
char User[STR_MAX];
char buf[MAXLEN];
char PUser[50];
char New_pw[50];
char Old_pw[50];
char WOld_pw[50];
char Wrest[MAXLEN];
char pwdfile[255] = PASSWD;
//char command[255];
char WUser[50];
char *cpw, salt[9];
char *tn, *cypher;
FILE *fpw, *tmp;
tn = NULL;
if((setuid(0)) < 0) eperror("setuid");
// unecessary: if((setgid(3)) < 0) eperror("setgid");
//sprintf(User,"%s",argv[1]);
snprintf(User, sizeof(User)-1, "%s", argv[1]);
User[sizeof(User)-1] = '\0';
//sprintf(Old_pw,"%s",argv[2]);
snprintf(Old_pw, sizeof(Old_pw)-1, "%s", argv[2]);
Old_pw[sizeof(Old_pw)-1] = '\0';
//sprintf(New_pw,"%s",argv[3]);
snprintf(New_pw, sizeof(New_pw)-1, "%s", argv[3]);
New_pw[sizeof(New_pw)-1] = '\0';
if(!strcmp("(null)",User)){
printf("Missing username\n");
return 12;
}
if(!strcmp("(null)",New_pw)){
printf("Missing new password\n");
return 2;
}
if(!strcmp("(null)",Old_pw)){
printf("Missing current password\n");
return 3;
}
if(!strcmp(User,"root")){
printf("The password for this user cannot be changed due to security constraints: %s\n",User);
return 4; //the root user cannot be edited for security reasons
}
fixpwd(New_pw);
fixpwd(Old_pw);
fixpwd(User);
if(!strcmp(Old_pw,New_pw)){
printf("The new password is equal to the current password. Choose another password.\n");
return 5;
}
if (access(SHADOW, R_OK) == 0){
sprintf(pwdfile, SHADOW);
test = 1;
}
//strcpy(PUser,User);
strncpy(PUser, User, sizeof(PUser)-1);
PUser[sizeof(PUser)-1] = '\0';
//strcat(PUser,":");
strncat(PUser, ":", sizeof(PUser)-1);
PUser[sizeof(PUser)-1] = '\0';
if((fpw=fopen(pwdfile,"r"))==NULL){
printf("Could not read password file: %s\n",pwdfile);
if(!test)
return 6; // means we are not using shadow pwd file
return 7; // means we are using shadow pwd file
}
tn = (char *)xmalloc(strlen(TMPFILE) + 1);
strcpy(tn, TMPFILE);
/*
mode_t oldUmask;
oldUmask = umask(0177);
...mkstemp()...
umask (oldUmask);
*/
umask(0177);
if ((tmp = fdopen((fdes = mkstemp(tn)), "w+")) == NULL) {
printf("Temporary file could not be opened: %s\n", tn);
return 8;
}
ok = 0;
while(fgets(buf,MAXLEN,fpw)!=NULL){
if(!ok){
if(strncmp(buf,PUser,strlen(PUser)) == 0){
getword(WUser,buf,':');
getword(WOld_pw,buf,':');
strcpy(Wrest,buf);
if(strcmp(WOld_pw, (char *)crypt(Old_pw, WOld_pw)) != 0){
if(fpw)
fclose(fpw);
if(tmp){
fclose(tmp);
close(fdes);
unlink(tn);
}
printf("Current password is incorrect\n");
return 9;
}
(void)srand((int)time((time_t *)NULL));
//cpw = (char *)crypt(New_pw,salt);
cypher = (char *)xmalloc(12); //MD5
strcpy(cypher, "$1$"); //MD5
strcat(cypher, salt); //MD5
cpw = (char *)crypt(New_pw, cypher); //MD5
sprintf(buf,"%s:%s:%s\n",User,cpw,Wrest);
buf[strlen(buf)-1]='\0';
ok++;
}
}
putline(tmp,buf);
}
fclose(fpw);
// fclose(tmp);
if(ok) {
//por nm@g only, en reemplazo del system cp, m<EFBFBD>s r<EFBFBD>pido y menos recursos
rewind(tmp);
if((fpw=fopen(pwdfile,"w"))==NULL){
printf("Could not read password file: %s\n",pwdfile);
if(!test)
return 6; // means we are not using shadow pwd file
return 7; // means we are using shadow pwd file
}
while( fgets(buf, MAXLEN, tmp) != NULL ) {
putline(fpw,buf);
}
fclose(fpw);
fclose(tmp);
close(fdes);
unlink(tn);
printf("The password was modified successfully\n");
return 0;
} else {
printf("User does not exist: %s\n", User);
fclose(tmp);
close(fdes);
unlink(tn);
return 10;
}
}
void eperror(s)
register char *s;
{
/*
Developed by
Pedro L Orso - orso@onda.com.br
Changed by
Thiago Melo de Paula - thiago@fafibe.br
*/
char str[50];
snprintf(str, sizeof(str)-1, "chpasswd - %s", s);
str[sizeof(str)-1] = '\0';
perror(str);
exit(1);
}
void getword(char *word, char *line, char stop)
{
/*
Developed by
Pedro L Orso - orso@onda.com.br
*/
int x = 0,y;
for(x=0;((line[x]) && (line[x] != stop));x++)
word[x] = line[x];
word[x] = '\0';
if(line[x]) ++x;
y=0;
while((line[y++] = line[x++]));
}
static void
fixpwd(str)
unsigned char *str;
{
/*
Developed by
Pedro L Orso - orso@onda.com.br
*/
unsigned char *dest = str;
while (str[0]) {
if (str[0] == '+')
dest[0] = ' ';
else if (str[0] == '%' && hhex(str[1]) && hhex(str[2])) {
dest[0] = (unsigned char) htoi(str + 1);
str += 2;
} else dest[0] = str[0];
str++;
dest++;
}
dest[0] = '\0';
return;
}
static int
htoi(s)
unsigned char *s;
{
/*
Developed by
Pedro L Orso - orso@onda.com.br
*/
int value;
char c;
c = s[0];
if (isupper(c))
c = tolower(c);
value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
c = s[1];
if (isupper(c))
c = tolower(c);
value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
return (value);
}
static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
/*
Developed by
Pedro L Orso - orso@onda.com.br
*/
void to64(s, v, n)
register char *s;
register long v;
register int n;
{
/*
Developed by
Pedro L Orso - orso@onda.com.br
Improved (md5) by nmag only <nmag@softhome.net>
*/
while (--n >= 0) {
*s++ = itoa64[v&0x3f];
v >>= 3;
v = ~v;
}
}
void putline(FILE *f,char *l) {
/*
Developed by
Pedro L Orso - orso@onda.com.br
*/
int x;
for(x=0;l[x];x++) fputc(l[x],f);
return;
}
// Developed by nmag only <nmag@softhome.net>
void *xmalloc (size_t size) {
register void *value = malloc(size);
if ( value == 0 ) {
printf("Virtual memory exhausted\n");
exit(11);
// exit(EXIT_FAILURE);
}
return value;
}