
/* Autentica empleando archivo propio de claves (como el generado con htpasswd),
 * No requiere privilegio de root, puede ejecutar un comando con el UID y
 * GID del usuario con el que corre.
 * Asume que archivo con usuarios y claves es "usuarios"
 * Dominio público. 2003. http://structio.sourceforge.net/sigue
 * 
 * Referencias: 

 */

#include <unistd.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

char *crypt(const char *,const char *);

static char salt[12], user[128], pass[128], cmd[1024]; 

void die(void) { 
	memset(salt, '\0', 12); 
	memset(user, '\0', 128); 
	memset(pass, '\0', 128); 
} 

/* Lo que se envié a stderr queda en log de errores de Apache */
void run() {
	if (system(cmd)!=0) {
		perror("problem running command");
	}
}

int main(int argc, char *argv[]) {
	char upass[1024];
	atexit(die); die(); 
	if (fscanf(stdin, "%127s %127s", user, pass) != 2) {
		warnx("unexpected input");
		return 1; 
	}

	if (getp("auth/usuarios",user,upass)!=0) {
		return 1;
	}
	if (upass[0] && 
	    !strcmp(crypt(pass, upass), upass)) {
		if (fgets(cmd,1024,stdin)!=NULL) {
			if (cmd[strlen(cmd)-1]=='\n') {
				cmd[strlen(cmd)-1]='\0';
			}
			run();
		}
		return 0;
	}
	warnx("incorrect password");

	return 1; 
} 

/** Opens htfile with users and passwords, looks for the user uname
 *  and returns the encrypted password in pass
 */
int getp(char *htfile, char *uname, char *pass)  {
	FILE *f;
	char *p;
	char lin[1024];

	if ((f=fopen(htfile,"r"))==NULL) {
		warnx("File doesn't exist");
		return -1;
	}
	
	pass[0]='\0';
	while (!feof(f) && pass[0]=='\0') {
		if (fgets(lin,1024,f)!=NULL) {
			if (lin[strlen(lin)-1]=='\n') {
				lin[strlen(lin)-1]='\0';
			}
			if ((p=strchr(lin,':'))!=NULL) {
				*p='\0';
				if (strcmp(lin,uname)==0) {
					strcpy(pass,p+1);
				}
			}
		}
	}
	fclose(f);
	if (pass[0]=='\0') {
		warnx("Unkown user");
		return -1;
	}
	return 0;
}
