#include "captive.h"


int main( int argc, char *argv[]) {

	/* Database stuff.  Uses the GNU hashed database library gdbm (free for all uses under the GPL).
		Home page:  http://www.gnu.org/software/gdbm/gdbm.html
		One of many sets of docs:  http://www.delorie.com/gnu/docs/gdbm/gdbm_toc.html
	   The database is keyed on username.  Each datum is a struct (userinfo, defined above) which
	   has the user's password, a flag to denote whether or not the account is enabled or not, and
	   the number of seconds before he is required to login again.
 	*/

	GDBM_FILE dbf;
	datum key;
	datum content;
	userinfo info;
	time_t tp;

	int i;
	int enabled=1;
	long secondsleft;
	float hoursleft;
	int hasupper=0, haslower=0, hasdigit=0;

	time( &tp );

	/* Check the command line arguments.  Self explanatory. */

	if( (argc != 4) && (argc != 5) ) {
		fprintf( stderr, "\n\tusage: captive_adduser [username] [password] [hours until re-login] {\"disabled\" | \"one-time\"}\n\n" );
		exit(0);
	}

	if( strlen(argv[1]) > USERNAME_LEN-1 ) {
		fprintf( stderr, "\n\tusage: captive_adduser [username] [password] [hours until re-login] {\"disabled\" | \"one-time\"}\n" );
		fprintf( stderr, "\tMax username length is %d characters\n\n", USERNAME_LEN-1 );
		exit(0);
	}
	if( strlen(argv[2]) > PASSWORD_LEN-1 ) {
		fprintf( stderr, "\n\tusage: captive_adduser [username] [password] [hours until re-login] {\"disabled\" | \"one-time\"}\n" );
		fprintf( stderr, "\tMax password length is %d characters\n\n", PASSWORD_LEN-1 );
		exit(0);
	}

	for( i = 0; i < strlen(argv[1]); i++ )
		if( !isalnum(argv[1][i]) ) {
			fprintf( stderr, "\n\tusage: captive_adduser [username] [password] [hours until re-login] {\"disabled\" | \"one-time\"}\n" );
			fprintf( stderr, "\tUsernames may contain alphanumeric characters only\n\n" );
			exit(0);
		}
	for( i = 0; i < strlen(argv[2]); i++ )
		if( !isalnum(argv[2][i]) ) {
			fprintf( stderr, "\n\tusage: captive_adduser [username] [password] [hours until re-login] {\"disabled\" | \"one-time\"}\n" );
			fprintf( stderr, "\tPasswords may contain alphanumeric characters only\n\n" );
			exit(0);
		}
	if( strlen(argv[2]) < MIN_PASSWORD_LEN ) {
		fprintf( stderr, "\n\tusage: captive_adduser [username] [password] [hours until re-login] {\"disabled\" | \"one-time\"}\n" );
		fprintf( stderr, "\tPasswords must be at least %d characters long\n\n", MIN_PASSWORD_LEN );
		exit(0);
	}
	for( i = 0; i < strlen(argv[2]); i++ ) {
		if( isupper(argv[2][i]) ) hasupper = 1;
		else if( islower(argv[2][i]) ) haslower = 1;
		else if( isdigit(argv[2][i]) ) hasdigit = 1;
	}
	if( !hasupper || !haslower || !hasdigit ) {
		fprintf( stderr, "\n\tusage: captive_adduser [username] [password] [hours until re-login] {\"disabled\" | \"one-time\"}\n" );
		fprintf( stderr, "\tPasswords must include an upper case character, a lower case character, and a digit\n\n" );
		exit(0);
	}

	/* User enters login duration in hours (decimals OK).  */

	hoursleft = atof( argv[3] );
	if( (hoursleft < .1) || (hoursleft > 168) ) {
		fprintf( stderr, "\n\tusage: captive_adduser [username] [password] [hours until re-login] {\"disabled\" | \"one-time\"}\n" );
		fprintf( stderr, "\tTime until re-login is forced must be between .1 and 168.0 hours (one week)\n\n" );
		exit(0);
	}
	secondsleft = (long)(hoursleft * 3600.0);

	if( argc == 5 ) {
		if( (strncmp(argv[4],"disabled",8) != 0) && (strncmp(argv[4],"one-time",8) != 0) ) {
			fprintf( stderr, "\n\tusage: captive_adduser [username] [password] [hours until re-login] {\"disabled\" | \"one-time\"}\n" );
			fprintf( stderr, "\tThird argument may only be \"disabled\" - if absent, enabled is assumed\n\n" );
			exit(0);
		}
		if( strncmp(argv[4],"disabled",8) == 0) enabled = 0;
		else enabled = 2;
	}


	printf( "Adding username/password %s/%s ", argv[1], argv[2] );
	if( enabled ) printf( "... " );
	else printf( "(disabled) ... " );


	dbf = gdbm_open( "/var/smoothwall/mods/captive/captivedb", 512, GDBM_WRCREAT, S_IRWXU, NULL );

	/* Database is keyed on username, which is 1st command line argument. */
	key.dptr = argv[1];
	key.dsize = strlen( argv[1] );

	content.dptr = (char *)&info;
	content.dsize = sizeof( info );
	strncpy( info.password, argv[2], PASSWORD_LEN );
	info.enabled = enabled;
	info.login_dur_in_seconds = secondsleft;
	info.logged_in_now = 0;
	info.ip[0] = '\0';
	info.mac[0] = '\0';
	info.login_expires_at = 0;

	if( gdbm_store(dbf,key,content,GDBM_REPLACE) == 0 ) {
		printf( "done.\n" );
	} else {
		printf( "failed.\n" );
	}

	gdbm_close( dbf );


	post_to_log( EVENT_USER_ADD, key.dptr, "N/A", "N/A", (long)tp );


	return 0;
}
