/* * AUTHOR: Pedro Lineu Orso * 1998, 2005 * CHPASSWD - Apache, Squid change passwd http://sarg-squid.org * * CHPASSWD donations: * please look at http://sarg-squid.org/donations.php * --------------------------------------------------------------------- * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */ #include "conf.h" #define MAXLEN 1024 #define hhex(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'a' && (x) <= 'f') || \ ((x) >= 'A' && (x) <= 'F')) char *tn; char template[255]="/var/tmp/chpasswd.XXXXXX"; int fd; FILE *fpw, *tmp; void getword(char *word, char *line, char stop) { 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++])); } void Hmsg(char *msg) { printf("Content-type: text/html\n"); puts("\n"); printf("\n"); printf("\n"); printf(" \n"); printf("\n"); printf("%s\n", msg); printf("\n"); return; } static void strip_latin(char *line) { char buf[255]; char warea[255]; while(strstr(line,"&") != 0){ getword(warea,line,'&'); strncat(warea,line,1); getword(buf,line,';'); strcat(warea,line); strcpy(line,warea); } return; } void sendmail(char *user, char *subj, char *msg) { FILE *mail; char cmd[MAXLEN]; sprintf(cmd,"mailx -s '%s' %s",subj,user); if (access("/bin/mailx", R_OK) == 0) sprintf(cmd,"/bin/mailx -s '%s' %s",subj,user); if (access("/usr/bin/mailx", R_OK) == 0) sprintf(cmd,"/bin/mailx -s '%s' %s",subj,user); if((mail =popen(cmd, "w")) != NULL ) { fputs(msg,mail); pclose(mail); } return; } void log(pwdlogfile, user, newpwd, showpwd, msg, pwdfile, smtpuser, smtpsubject) unsigned char *pwdlogfile; unsigned char *user; unsigned char *newpwd; unsigned char *showpwd; unsigned char *msg; unsigned char *pwdfile; unsigned char *smtpuser; unsigned char *smtpsubject; { FILE *fp_ou; char Msg[MAXLEN]; time_t tm; struct tm *t; char time_string[128]; char pwd[MAXLEN]; tm = time(NULL); t = localtime(&tm); strftime(time_string, 127, "%Y/%m/%d %H:%M:%S", t); if ((fp_ou = fopen(pwdlogfile, "a")) == NULL) { sprintf(Msg, "%s %s",msg16, pwdlogfile); Hmsg(Msg); exit(1); } Msg[0]='\0'; strcpy(pwd,"-"); if(strcmp(showpwd,"yes") == 0){ if(strlen(newpwd) > 0) strcpy(pwd,newpwd); } if(strlen(user) == 0) strcpy(user,"-"); sprintf(Msg, "%s %s %s %s %s pwdfile=%s\n",getenv("REMOTE_ADDR"),time_string,user,pwd,msg,pwdfile); Msg[strlen(Msg)-1]='\n'; strip_latin(Msg); fputs(Msg,fp_ou); fclose(fp_ou); if(strlen(smtpuser) > 0) sendmail(smtpuser,smtpsubject,Msg); return; } void Herror(char *msg) { printf("Content-type: text/html\n"); puts("\n"); printf("\n"); printf("\n"); printf(" \n"); printf("\n"); printf("%s\n", msg); printf("\n"); if (fpw) fclose(fpw); if (tmp) { fclose(tmp); unlink(template); } return; } void putline(FILE * f, char *l) { int x; for (x = 0; l[x]; x++) fputc(l[x], f); // fputc('\n',f); } static unsigned char itoa64[] = /* * 0 ... 63 => ascii - 64 */ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; to64(s, v, n) register char *s; register long v; register int n; { while (--n >= 0) { *s++ = itoa64[v & 0x3f]; v >>= 6; } } void Changed(char *user, char *PwdLogFile, char *newpwd, char *showpwd, char *PwdFile, char *SmtpUser, char *SmtpSubject) { char Msg[MAXLEN]; printf("Content-type: text/html\n"); puts("\n"); printf("\n"); printf("\n"); printf(" \n"); printf("\n"); printf("\n"); sprintf(Msg, "%s %s %s",msg11, user, msg12); printf(Msg); printf("\n"); printf("\n"); if(strlen(PwdLogFile) > 0) log(PwdLogFile,user,newpwd,showpwd,Msg,PwdFile,SmtpUser,SmtpSubject); return; } void NotFound(char *user, char *PwdLogFile, char *newpwd, char *showpwd, char *PwdFile, char *SmtpUser, char *SmtpSubject) { char Msg[MAXLEN]; printf("Content-type: text/html\n"); puts("\n"); printf("\n"); printf("\n"); printf(" \n"); printf("\n"); printf("\n"); sprintf(Msg, "%s %s %s",msg13, user, msg14); printf(Msg); printf("\n"); printf("\n"); if(strlen(PwdLogFile) > 0) log(PwdLogFile,user,newpwd,showpwd,Msg,PwdFile,SmtpUser,SmtpSubject); return; } static void fixpwd(str) unsigned char *str; { 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; } int htoi(s) unsigned char *s; { 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); } void rulefail(char *minchar, char *minnum, char *minspec) { char Msg[MAXLEN]; printf("Content-type: text/html\n"); puts("\n"); printf("\n"); printf("\n"); printf(" \n"); printf("\n"); printf(""); sprintf(Msg,"%s

",msg17); printf(Msg); sprintf(Msg,"%s

\n",msg18); printf(Msg); if(strcmp(minchar,"0") != 0) printf("\n",msg19,minchar); else printf("
%s%s
\n",msg19); if(strcmp(minnum,"0") != 0) printf("\n",msg20,minnum); else printf("\n",msg20); if(strcmp(minspec,"0") != 0) printf("\n",msg21,minspec); else printf("\n",msg21); printf("
%s
%s%s
%s
%s%s
%s
\n"); exit(1); } void getconf(ConfigFile, IpAuth, PwdFile, PwdMinLen, PwdMaxLen, PwdMinChar, PwdMinNum, PwdMinSpec, PwdLogFile, ShowPwd, BgColor, TxColor, TiColor, RuColor, Logo, Width, Height, Header, BgImage, SmtpUser, SmtpSubject, ShowInfo) unsigned char *ConfigFile; unsigned char *PwdFile; unsigned char *IpAuth; unsigned char *PwdLogFile; unsigned char *ShowPwd; unsigned char *PwdMinLen; unsigned char *PwdMaxLen; unsigned char *PwdMinChar; unsigned char *PwdMinNum; unsigned char *PwdMinSpec; unsigned char *BgColor; unsigned char *TxColor; unsigned char *TiColor; unsigned char *RuColor; unsigned char *Logo; unsigned char *Width; unsigned char *Height; unsigned char *Header; unsigned char *BgImage; unsigned char *SmtpUser; unsigned char *SmtpSubject; unsigned char *ShowInfo; { FILE *fp_in; char buf[255]; char wbuf[255]; char Msg[255]; char *str; // bzero(NcsaPlus,5); // bzero(ShowInfo,5); if ((fp_in = fopen(ConfigFile, "r")) == NULL) { sprintf(Msg, "%s %s", msg15, ConfigFile); Hmsg(Msg); exit(1); } while (fgets(buf, MAXLEN, fp_in) != NULL) { if((str=(char *) strstr(buf,"#")) != (char *) NULL) continue; if(strstr(buf,"password_file") != 0) { getword(wbuf,buf,' '); getword(PwdFile,buf,' '); PwdFile[strlen(PwdFile)-1]='\0'; } if(strstr(buf,"ip_auth") != 0) { getword(wbuf,buf,' '); getword(IpAuth,buf,' '); IpAuth[strlen(IpAuth)-1]='\0'; } if(strstr(buf,"minimum_length") != 0) { getword(wbuf,buf,' '); getword(PwdMinLen,buf,' '); PwdMinLen[strlen(PwdMinLen)-1]='\0'; } if(strstr(buf,"maximum_length") != 0) { getword(wbuf,buf,' '); getword(PwdMaxLen,buf,' '); PwdMaxLen[strlen(PwdMaxLen)-1]='\0'; } if(strstr(buf,"minimum_char") != 0) { getword(wbuf,buf,' '); getword(PwdMinChar,buf,' '); PwdMinChar[strlen(PwdMinChar)-1]='\0'; } if(strstr(buf,"minimum_num") != 0) { getword(wbuf,buf,' '); getword(PwdMinNum,buf,' '); PwdMinNum[strlen(PwdMinNum)-1]='\0'; } if(strstr(buf,"minimum_spec") != 0) { getword(wbuf,buf,' '); getword(PwdMinSpec,buf,' '); PwdMinSpec[strlen(PwdMinSpec)-1]='\0'; } if(strstr(buf,"enable_log") != 0) { getword(wbuf,buf,' '); getword(PwdLogFile,buf,'\0'); PwdLogFile[strlen(PwdLogFile)-1]='\0'; } if(strstr(buf,"show_pwd") != 0) { getword(wbuf,buf,' '); getword(ShowPwd,buf,'\0'); ShowPwd[strlen(ShowPwd)-1]='\0'; } if(strstr(buf,"background_color") != 0) { getword(wbuf,buf,' '); getword(BgColor,buf,'\0'); BgColor[strlen(BgColor)-1]='\0'; } if(strstr(buf,"text_color") != 0) { getword(wbuf,buf,' '); getword(TxColor,buf,'\0'); TxColor[strlen(TxColor)-1]='\0'; } if(strstr(buf,"title_color") != 0) { getword(wbuf,buf,' '); getword(TiColor,buf,'\0'); TiColor[strlen(TiColor)-1]='\0'; } if(strstr(buf,"rules_color") != 0) { getword(wbuf,buf,' '); getword(RuColor,buf,'\0'); RuColor[strlen(RuColor)-1]='\0'; } if(strstr(buf,"logo_image") != 0) { getword(wbuf,buf,' '); getword(Logo,buf,'\0'); Logo[strlen(Logo)-1]='\0'; } if(strstr(buf,"background_image") != 0) { getword(wbuf,buf,' '); getword(BgImage,buf,'\0'); BgImage[strlen(BgImage)-1]='\0'; } if(strstr(buf,"alert_mail_user") != 0) { getword(wbuf,buf,' '); getword(SmtpUser,buf,'\0'); SmtpUser[strlen(SmtpUser)-1]='\0'; } if(strstr(buf,"ncsa_plus") != 0) { getword(wbuf,buf,' '); getword(NcsaPlus,buf,'\0'); NcsaPlus[strlen(NcsaPlus)-1]='\0'; } if(strstr(buf,"show_info") != 0) { getword(wbuf,buf,' '); getword(ShowInfo,buf,'\0'); ShowInfo[strlen(ShowInfo)-1]='\0'; } if(strstr(buf,"alert_mail_subject") != 0) { getword(wbuf,buf,'"'); getword(SmtpSubject,buf,'"'); } if(strstr(buf,"image_size") != 0) { getword(wbuf,buf,' '); getword(Width,buf,' '); getword(Height,buf,'\0'); Height[strlen(Height)-1]='\0'; } if(strstr(buf,"header") != 0) { getword(wbuf,buf,'"'); getword(Header,buf,'"'); } } fclose(fp_in); return; } static void vrfyrule(unsigned char *str, unsigned char *minchar, unsigned char *minnum, unsigned char *minspec) { int tnum=0, talfa=0, tspec=0; char *ostr = str; while(str[0]) { if (str[0] == '%' && hhex(str[1]) && hhex(str[2])) { tspec++; str=str+3; continue; } if (str[0] == '.') { tspec++; str++; continue; } if ((str[0] >= 'a' && str[0] <= 'z') || (str[0] >='A' && str[0] <= 'Z')) talfa++; if (str[0] >= '0' && str[0] <= '9') tnum++; str++; } if(talfa < atoi(minchar)) rulefail(minchar,minnum,minspec); if(tnum < atoi(minnum)) rulefail(minchar,minnum,minspec); if(tspec < atoi(minspec)) rulefail(minchar,minnum,minspec); return; } static void vrfyauth(char *authfile, char *PwdLogFile, char *PwdFile, char *SmtpUser, char *SmtpSubject) { FILE *auth; char IP[30]; char buf[MAXLEN]; int authbit=0; struct stat statb; if(stat(authfile,&statb)) eperror(authfile); if(statb.st_uid != 0) { Hmsg(msg23); if(strlen(PwdLogFile) > 0) log(PwdLogFile,"-","","no",msg23,PwdFile,SmtpUser,SmtpSubject); exit(1); } if(statb.st_mode & 022) { Hmsg(msg24); if(strlen(PwdLogFile) > 0) log(PwdLogFile,"-","","no",msg24,PwdFile,SmtpUser,SmtpSubject); exit(1); } if((auth=fopen(authfile,"r"))==NULL) { Hmsg(msg25); if(strlen(PwdLogFile) > 0) log(PwdLogFile,"-","","no",msg25,PwdFile,SmtpUser,SmtpSubject); exit(1); } if(getenv("HTTP_X_FORWARDED_FOR")) sprintf(IP,"%s",getenv("HTTP_X_FORWARDED_FOR")); else sprintf(IP,"%s",getenv("REMOTE_ADDR")); while(fgets(buf,MAXLEN,auth)!=NULL) { if(!authbit) { if(strstr(buf,"#") != 0) continue; else authbit=vauth(buf,IP); } } if(!authbit) { Hmsg(msg26); if(strlen(PwdLogFile) > 0) log(PwdLogFile,"-","","no",msg26,PwdFile,SmtpUser,SmtpSubject); exit(1); } return; } int vauth(char *buf, char *ip) { char a1[4],a2[4],a3[4],a4[4]; char o1[4],o2[4],o3[4],o4[4]; char ip2[255]; int ok=1; strcpy(ip2,ip); buf[strlen(buf)-1]='\0'; if(strcmp(buf,"0.0.0.0") == 0) return(1); if(strcmp(buf,ip2) == 0) return(1); getword(a1,buf,'.'); getword(a2,buf,'.'); getword(a3,buf,'.'); getword(a4,buf,' '); getword(o1,ip2,'.'); getword(o2,ip2,'.'); getword(o3,ip2,'.'); getword(o4,ip2,' '); if(strcmp(a1,"0") != 0){ if(strcmp(a1,o1) != 0) ok=0; } if(strcmp(a2,"0") != 0){ if(strcmp(a2,o2) != 0) ok=0; } if(strcmp(a3,"0") != 0){ if(strcmp(a3,o3) != 0) ok=0; } if(strcmp(a4,"0") != 0){ if(strcmp(a4,o4) != 0) ok=0; } return(ok); } eperror(s) register char *s; { perror("chpasswd.cgi"); exit(1); } void getword(char *, char *, char); void Herror(char *); void Hmsg(char *); void putline(FILE *, char *); void Changed(char *, char *, char *, char *, char *, char *, char *); void NotFound(char *, char *, char *, char *, char *, char *, char *); void rulefail(char *, char *, char *); static void strip_latin(char *); void sendmail(char *, char *, char *); main(argc, argv) int argc; char *argv[]; { char buf[MAXLEN]; char User[255]; char PUser[255]; char WUser[255]; char Old_pw[255]; char WOld_pw[255]; char New_pw1[255]; char New_pw2[255]; char Action[255]; char Msg[MAXLEN]; char command[255]; char PwdFile[MAXLEN]="/usr/local/squid/etc/passwd"; char IpAuth[MAXLEN]=""; char PwdMinLen[255]="4"; char PwdMaxLen[255]="10"; char ShowPwd[255]="no"; char PwdMinChar[255]="0"; char PwdMinNum[255]="0"; char PwdMinSpec[255]="0"; char BgColor[255]="white"; char TiColor[255]="green"; char TxColor[255]="blue"; char RuColor[255]="red"; char Logo[MAXLEN]=""; char Width[MAXLEN]="80"; char Height[MAXLEN]="80"; char Header[MAXLEN]; char BgImage[MAXLEN]=""; char SmtpUser[MAXLEN]=""; char SmtpSubject[MAXLEN]="CHPASSWD EVENT"; char InputBuffer[1024]; char ConfigFile[255]; char PwdLogFile[255]; char ShowInfo[5]="on"; char authorized_ip[20]; char *pContentLength; char *str; char *cpw, salt[3]; int ContentLength; int i; int x, ok = 0; tn = NULL; fpw = NULL; tmp = NULL; buf[0]='\0'; User[0]='\0'; PUser[0]='\0'; WUser[0]='\0'; Old_pw[0]='\0'; WOld_pw[0]='\0'; New_pw1[0]='\0'; New_pw2[0]='\0'; Action[0]='\0'; Msg[0]='\0'; command[0]='\0'; PwdLogFile[0]='\0'; strcpy(Header,msg22); sprintf(ConfigFile,"%s/chpasswd.conf",PREFIX); if (access(ConfigFile, R_OK) == 0) { getconf(ConfigFile,IpAuth,PwdFile,PwdMinLen,PwdMaxLen,PwdMinChar,PwdMinNum,PwdMinSpec,PwdLogFile,ShowPwd,BgColor,TxColor,TiColor,RuColor,Logo,Width,Height,Header,BgImage,SmtpUser,SmtpSubject,ShowInfo); } if (strlen(IpAuth) > 0 ) { if (access(IpAuth, R_OK) != 0) { Hmsg(msg27); if(strlen(PwdLogFile) > 0) log(PwdLogFile,"-","","no",msg27,PwdFile,SmtpUser,SmtpSubject); exit(1); } vrfyauth(IpAuth,PwdLogFile,PwdFile,SmtpUser,SmtpSubject); } if (strcmp(getenv("REQUEST_METHOD"), "GET") == 0) { UserForm(PwdMinLen,PwdMaxLen,PwdMinChar,PwdMinNum,PwdMinSpec,BgColor,TxColor,TiColor,RuColor,Logo,Width,Height,Header,BgImage,ShowInfo); return; } pContentLength = getenv("CONTENT_LENGTH"); if (pContentLength != NULL) ContentLength = atoi(pContentLength); else ContentLength = 0; if (ContentLength > sizeof(InputBuffer) - 1) { ContentLength = sizeof(InputBuffer) - 1; } i = 0; while (i < ContentLength) { x = fgetc(stdin); if (x == EOF) break; InputBuffer[i++] = x; } InputBuffer[i] = '\0'; ContentLength = i; getword(User, InputBuffer, '='); getword(User, InputBuffer, '&'); getword(Old_pw, InputBuffer, '='); getword(Old_pw, InputBuffer, '&'); getword(New_pw1, InputBuffer, '='); getword(New_pw1, InputBuffer, '&'); getword(New_pw2, InputBuffer, '='); getword(New_pw2, InputBuffer, '&'); getword(Action, InputBuffer, '='); if(atoi(PwdMinChar) || atoi(PwdMinNum) || atoi(PwdMinSpec)) vrfyrule(New_pw1,PwdMinChar,PwdMinNum,PwdMinSpec); fixpwd(Old_pw); fixpwd(New_pw1); fixpwd(New_pw2); if (strcmp(Action, "change") == 0) { if (strlen(New_pw1) < atoi(PwdMinLen)) { sprintf(Msg, "%s %s %s",msg02, PwdMinLen, msg03); if(strlen(PwdLogFile) > 0) log(PwdLogFile,User,New_pw1,ShowPwd,Msg,PwdFile,SmtpUser,SmtpSubject); Herror(Msg); return; } if (strlen(New_pw1) > atoi(PwdMaxLen)) { sprintf(Msg, "%s %s %s",msg04, PwdMaxLen, msg03); if(strlen(PwdLogFile) > 0) log(PwdLogFile,User,New_pw1,ShowPwd,Msg,PwdFile,SmtpUser,SmtpSubject); Herror(Msg); return; } if (strcmp(Old_pw, New_pw1) == 0) { sprintf(Msg, "%s",msg05); if(strlen(PwdLogFile) > 0) log(PwdLogFile,User,New_pw1,ShowPwd,Msg,PwdFile,SmtpUser,SmtpSubject); Herror(Msg); return; } if (strcmp(New_pw1, New_pw2) != 0) { sprintf(Msg, "%s",msg06); if(strlen(PwdLogFile) > 0) log(PwdLogFile,User,New_pw1,ShowPwd,Msg,PwdFile,SmtpUser,SmtpSubject); Herror(Msg); return; } if ((fpw = fopen(PwdFile, "r")) == NULL) { sprintf(Msg, "%s %s",msg07, PwdFile); Herror(Msg); return; } fd = mkstemp(template); if((fd == -1 ) || ((tmp = fdopen (fd, "w+" )) == NULL) ) { /* failure, bail out */ sprintf(Msg, "%s",msg08); Herror(Msg); return; } while (fgets(buf, MAXLEN, fpw) != NULL) { if (!ok) { strcpy(PUser,User); strcat(PUser,":"); if ((str = (char *) strstr(buf, PUser)) != (char *) NULL ) { getword(WUser, buf, ':'); if(strncmp(NcsaPlus,"on",2) == 0) { getword(WOld_pw, buf, ':'); getword(authorized_ip, buf, ':'); strcpy(authorized_ip,buf); } else getword(WOld_pw, buf, '\n'); if (strcmp(WOld_pw, crypt(Old_pw, WOld_pw)) != 0) { sprintf(Msg, "%s %s",msg09, User); if(strlen(PwdLogFile) > 0) log(PwdLogFile,User,New_pw1,ShowPwd,Msg,PwdFile,SmtpUser,SmtpSubject); Herror(Msg); return; } (void) srand((int) time((time_t *) NULL)); to64(&salt[0], rand(), 2); cpw = crypt(New_pw1, salt); if(strncmp(NcsaPlus,"on",2) == 0) { tm = time(NULL); t = localtime(&tm); strftime(ttime, 127, "%d/%m/%Y-%H%M", t); sprintf(buf, "%s:%s:%s:%s\n", User, cpw, ttime, authorized_ip); } else sprintf(buf, "%s:%s\n", User, cpw); ok++; } } putline(tmp, buf); } fclose(fpw); fclose(tmp); if ((tmp = fopen(template, "r")) == NULL) { sprintf(Msg, "%s",msg08); Herror(Msg); return; } if ((fpw = fopen(PwdFile, "w")) == NULL) { sprintf(Msg, "%s",msg07); Herror(Msg); return; } while (fgets(buf, MAXLEN, tmp) != NULL) fputs(buf,fpw); fclose(fpw); fclose(tmp); unlink(template); if (ok) Changed(User, PwdLogFile, New_pw1, ShowPwd, PwdFile, SmtpUser, SmtpSubject); else NotFound(User, PwdLogFile, New_pw1, ShowPwd, PwdFile, SmtpUser, SmtpSubject); } else { if (strcmp(Action, "cancel") == 0) { sprintf(Msg, "%s",msg10); if(strlen(PwdLogFile) > 0) log(PwdLogFile,User,New_pw1,ShowPwd,Msg,PwdFile,SmtpUser,SmtpSubject); Herror(Msg); return; } } return; }