/* * htpasswd.c: simple program for manipulating password file for NCSA httpd * * Rob McCool *--- * * Modified locally to use MD5 digest instead of crypt(). * R. Perry, May 1997 */ #include #include #include #include #include #include "des.h" #include "md5.h" #define LF 10 #define CR 13 #define MAX_STRING_LEN BUFSIZ char *tn; char *strd(char *s) { char *d; if( (d=(char *)malloc(strlen(s) + 1)) == NULL) { fprintf( stderr, "htpasswd: malloc() failed.\n"); exit(1); } strcpy(d,s); return(d); } 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++])); } int getline(char *s, int n, FILE *f) { register int i=0; while(1) { s[i] = (char)fgetc(f); if(s[i] == CR) s[i] = fgetc(f); if((s[i] == 0x4) || (s[i] == LF) || (i == (n-1))) { s[i] = '\0'; return (feof(f) ? 1 : 0); } ++i; } } void putline(FILE *f,char *l) { int x; for(x=0;l[x];x++) fputc(l[x],f); fputc('\n',f); } void add_password(char *user, FILE *f) { char md5_input[ 2*MAX_STRING_LEN]; char pw[MAX_STRING_LEN]; unsigned char *md; int status, i; status = des_read_pw_string( pw, sizeof pw, "New password:", 1); if( status != 0) { fprintf( stderr, "des_read_pw_string: %s\n", status < 0 ? "system error" : "mismatch"); if( tn) unlink( tn); exit(1); } sprintf( md5_input, "%s:%s", user, pw); #ifdef DEBUG fprintf( stderr, "htpasswd: MD5 input is '%s'\n", md5_input); #endif md = MD5( (unsigned char *) md5_input, strlen(md5_input), NULL); fprintf( f, "%s:", user); for( i = 0; i < MD5_DIGEST_LENGTH; ++i) fprintf( f, "%02x", md[i]); fprintf( f, "\n"); } void usage() { fprintf(stderr,"Usage: htpasswd [-c] passwordfile username\n"); fprintf(stderr,"The -c flag creates a new file.\n"); exit(1); } void interrupted() { fprintf(stderr,"Interrupted.\n"); if(tn) unlink(tn); exit(1); } void main(int argc, char *argv[]) { FILE *tfp,*f; char user[MAX_STRING_LEN]; char line[MAX_STRING_LEN]; char l[MAX_STRING_LEN]; char w[MAX_STRING_LEN]; char command[MAX_STRING_LEN]; int found; tn = NULL; signal(SIGINT,(void (*)())interrupted); if(argc == 4) { if(strcmp(argv[1],"-c")) usage(); if(!(tfp = fopen(argv[2],"w"))) { fprintf(stderr,"Could not open passwd file %s for writing.\n", argv[2]); perror("fopen"); exit(1); } printf("Adding password for %s.\n",argv[3]); add_password(argv[3],tfp); fclose(tfp); exit(0); } else if(argc != 3) usage(); tn = tmpnam(NULL); if(!(tfp = fopen(tn,"w"))) { fprintf(stderr,"Could not open temp file.\n"); exit(1); } if(!(f = fopen(argv[1],"r"))) { fprintf(stderr, "Could not open passwd file %s for reading.\n",argv[1]); fprintf(stderr,"Use -c option to create new one.\n"); exit(1); } strcpy(user,argv[2]); found = 0; while(!(getline(line,MAX_STRING_LEN,f))) { if(found || (line[0] == '#') || (!line[0])) { putline(tfp,line); continue; } strcpy(l,line); getword(w,l,':'); if(strcmp(user,w)) { putline(tfp,line); continue; } else { printf("Changing password for user %s\n",user); add_password(user,tfp); found = 1; } } if(!found) { printf("Adding user %s\n",user); add_password(user,tfp); } fclose(f); fclose(tfp); sprintf(command,"/bin/cp %s %s",tn,argv[1]); system(command); unlink(tn); }