
/* Verifica acceso a un sistema OpenBSD en el que no se usa ni Kerberos
 * ni YP. Opcionalmente permite ejecutar un comando con el UID y GID
 * del usuario. Dominio público. 2003.
 * http://structio.sourceforge.net/sigue
 * 
 * Referencias: 
 * man getpwman.0
 * Ayuda de darryl at pointclark dot net en http://de.php.net/posix_getpwnam 
 * /usr/src/usr.bin/passwd/local_passwd.c */

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

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 /var/www/logs/error_log */
void run(uid_t uid, gid_t gid) {
	char *s;
	FILE *t;
	if (seteuid(uid)!=0) {
		perror("cannot set uid");
	}
/* apache debe ser del grupo profesores  	if (setegid(gid)!=0) {
		asprintf(&s,"cannot set gid %i",gid);
		perror(s);
		free(s);
	}  */

	if (system(cmd)!=0) {
		perror("problem running command");
	}
}

int main(int argc, char *argv[]) {
	struct passwd *pw;
	atexit(die); die(); 
	if (fscanf(stdin, "%127s %127s", user, pass) != 2) {
		warnx("unexpected input");
		return 1; 
	}
	
	if(!(pw=getpwnam(user))) {
		warnx("unknown user");
		return 1; 
	}
	if (pw->pw_passwd[0]=='*') {
		warnx("root must run this program");
		return 1; 
	}
	if (pw->pw_passwd[0] && 
	    !strcmp(crypt(pass, pw->pw_passwd), pw->pw_passwd)) {
		if (fgets(cmd,1024,stdin)!=NULL) {
			if (cmd[strlen(cmd)-1]=='\n') {
				cmd[strlen(cmd)-1]='\0';
			}
			run(pw->pw_uid,pw->pw_gid);
		}
		return 0;
	}
	warnx("incorrect password");

	return 1; 
} 
