1
0
mirror of https://git.FreeBSD.org/ports.git synced 2025-01-23 09:10:43 +00:00
freebsd-ports/www/thttpd/files/patch-extras_htpasswd.c
Alexey Dokuchaev a6b9b8a7a9 Update `www/thttpd' to version 2.28, which features:
- Improvements to the FreeBSD startup script (Craig Leres)
  - Minor portability tweak in mmc.c
  - Fix a potential buffer overrun bug in htpasswd (reported
    by Alessio Santoru as CVE-2017-17663), no-op on FreeBSD
    due to our custom patches from Red Hat since r377324

PR:	225701
2018-02-08 14:26:28 +00:00

201 lines
6.2 KiB
C

--- extras/htpasswd.c.orig 2001-12-19 00:08:08 UTC
+++ extras/htpasswd.c
@@ -19,7 +19,12 @@
#define LF 10
#define CR 13
+#define CPW_LEN 13
+
+/* ie 'string' + '\0' */
#define MAX_STRING_LEN 256
+/* ie 'maxstring' + ':' + cpassword */
+#define MAX_LINE_LEN MAX_STRING_LEN+1+CPW_LEN
int tfd;
char temp_template[] = "/tmp/htp.XXXXXX";
@@ -135,8 +140,9 @@ add_password( char* user, FILE* f )
}
static void usage(void) {
- fprintf(stderr,"Usage: htpasswd [-c] passwordfile username\n");
- fprintf(stderr,"The -c flag creates a new file.\n");
+ fprintf(stderr,"Usage: htpasswd [-c] passwordfile username\n"
+ "The -c flag creates a new file.\n"
+ "Will prompt for password, unless given on stdin.\n");
exit(1);
}
@@ -149,52 +155,129 @@ void interrupted(int signo) {
int main(int argc, char *argv[]) {
FILE *tfp,*f;
char user[MAX_STRING_LEN];
- char line[MAX_STRING_LEN];
- char l[MAX_STRING_LEN];
+ char pwfilename[MAX_STRING_LEN];
+ char line[MAX_LINE_LEN];
+ char l[MAX_LINE_LEN];
char w[MAX_STRING_LEN];
- char command[MAX_STRING_LEN];
- int found;
+ int found,u;
tfd = -1;
+ u = 2; /* argv[u] is username, unless... */
signal(SIGINT,(void (*)(int))interrupted);
if(argc == 4) {
+ u = 3;
if(strcmp(argv[1],"-c"))
usage();
+ if((f=fopen(argv[2],"r")) != NULL) {
+ fclose(f);
+ fprintf(stderr,
+ "Password file %s already exists.\n"
+ "Delete it first, if you really want to overwrite it.\n",
+ argv[2]);
+ exit(1);
+ }
+ } else if(argc != 3) usage();
+ /* check uname length; underlying system will take care of pwdfile
+ name too long */
+ if (strlen(argv[u]) >= MAX_STRING_LEN) {
+ fprintf(stderr,"Username too long (max %i): %s\n",
+ MAX_STRING_LEN-1, argv[u]);
+ exit(1);
+ }
+
+ if(argc == 4) {
if(!(tfp = fopen(argv[2],"w"))) {
fprintf(stderr,"Could not open passwd file %s for writing.\n",
argv[2]);
perror("fopen");
exit(1);
}
+ if (strlen(argv[2]) > (sizeof(pwfilename) - 1)) {
+ fprintf(stderr, "%s: filename is too long\n", argv[0]);
+ exit(1);
+ }
+ if (((strchr(argv[2], ';')) != NULL) || ((strchr(argv[2], '>')) != NULL)) {
+ fprintf(stderr, "%s: filename contains an illegal character\n",
+ argv[0]);
+ exit(1);
+ }
+ if (strlen(argv[3]) > (sizeof(user) - 1)) {
+ fprintf(stderr, "%s: username is too long\n", argv[0]);
+ exit(1);
+ }
+ if ((strchr(argv[3], ':')) != NULL) {
+ fprintf(stderr, "%s: username contains an illegal character\n",
+ argv[0]);
+ exit(1);
+ }
printf("Adding password for %s.\n",argv[3]);
add_password(argv[3],tfp);
fclose(tfp);
exit(0);
- } else if(argc != 3) usage();
+ }
- tfd = mkstemp(temp_template);
- if(!(tfp = fdopen(tfd,"w"))) {
- fprintf(stderr,"Could not open temp file.\n");
+ if (strlen(argv[1]) > (sizeof(pwfilename) - 1)) {
+ fprintf(stderr, "%s: filename is too long\n", argv[0]);
+ exit(1);
+ }
+ if (((strchr(argv[1], ';')) != NULL) || ((strchr(argv[1], '>')) != NULL)) {
+ fprintf(stderr, "%s: filename contains an illegal character\n",
+ argv[0]);
+ exit(1);
+ }
+ if (strlen(argv[2]) > (sizeof(user) - 1)) {
+ fprintf(stderr, "%s: username is too long\n", argv[0]);
+ exit(1);
+ }
+ if ((strchr(argv[2], ':')) != NULL) {
+ fprintf(stderr, "%s: username contains an illegal character\n",
+ argv[0]);
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);
}
+ if(freopen(argv[1],"a",f) == NULL) {
+ fprintf(stderr,
+ "Could not open passwd file %s for writing!.\n"
+ "Changes would be lost.\n",argv[1]);
+ exit(1);
+ }
+ f = freopen(argv[1],"r",f);
+
+ /* pwdfile is there, go on with tempfile now ... */
+ tfd = mkstemp(temp_template);
+ if(!(tfp = fdopen(tfd,"w"))) {
+ fprintf(stderr,"Could not open temp file.\n");
+ exit(1);
+ }
+ /* already checked for boflw ... */
strncpy(user,argv[2],sizeof(user)-1);
user[sizeof(user)-1] = '\0';
found = 0;
- while(!(my_getline(line,MAX_STRING_LEN,f))) {
+ /* line we get is username:pwd, or possibly any other cruft */
+ while(!(my_getline(line,MAX_LINE_LEN,f))) {
+ char *i;
+
if(found || (line[0] == '#') || (!line[0])) {
putline(tfp,line);
continue;
}
- strcpy(l,line);
- getword(w,l,':');
+ i = index(line,':');
+ w[0] = '\0';
+ /* actually, cpw is CPW_LEN chars and never null, hence ':' should
+ always be at line[strlen(line)-CPW_LEN-1] in a valid user:cpw line
+ Here though we may allow for pre-hancrafted pwdfile (!)...
+ But still need to check for length limits.
+ */
+ if (i != 0 && i-line <= MAX_STRING_LEN-1) {
+ strcpy(l,line);
+ getword(w,l,':');
+ }
if(strcmp(user,w)) {
putline(tfp,line);
continue;
@@ -208,10 +291,28 @@ int main(int argc, char *argv[]) {
printf("Adding user %s\n",user);
add_password(user,tfp);
}
+ /* close, rewind & copy */
+ fclose(f);
+ fclose(tfp);
+ f = fopen(argv[1],"w");
+ if(f==NULL) {
+ fprintf(stderr,"Failed re-opening %s!?\n",argv[1]);
+ exit(1);
+ }
+ tfp = fopen(temp_template,"r");
+ if(tfp==NULL) {
+ fprintf(stderr,"Failed re-opening tempfile!?\n");
+ exit(1);
+ }
+ {
+ int c;
+ while((c=fgetc(tfp))!=EOF && !feof(tfp)) {
+ fputc(c,f);
+ /* fputc(c,stderr); */
+ }
+ }
fclose(f);
fclose(tfp);
- sprintf(command,"cp %s %s",temp_template,argv[1]);
- system(command);
unlink(temp_template);
exit(0);
}