#include <string.h>
#include <dce/keymgmt.h>
#include <dce/binding.h>
#include <dce/misc.h>
#include <dce/acct.h>

#include "DceLogin.h"

#include <stdio.h>


DceLogin::DceLogin():
status(0),
login_context(0),
login_flags(sec_login_no_flags),
is_logged(false)
{
	password_record.version_number = sec_passwd_c_version_none;
	password_record.pepper = 0;
	password_record.key.key_type = sec_passwd_plain;	
}

DceLogin::~DceLogin()
{
	error_status_t s=0;
	if(is_logged)
		sec_login_release_context(&login_context,&s);
}
	
	
int DceLogin::login(const char* principal_name,const char* password)
{
	error_status_t s=0;
	boolean32 r=FALSE;
	boolean32 reset_password=FALSE;
	sec_passwd_str_t  tmp_password;
	
	password_record.key.tagged_union.plain=&(tmp_password[0]);
		
	if(	is_logged || 
		strlen(principal_name) > 1000 || 
		strlen(password) > sec_passwd_str_max_len
	)
		return 1;
	
	strncpy((char*)tmp_password,password,sec_passwd_str_max_len);
	tmp_password[sec_passwd_str_max_len] = '\0';
	
		
	r=sec_login_setup_identity(
	(unsigned char*)principal_name,
	login_flags,
	&login_context,
	&s);
	
	if(s!=error_status_ok || r!=TRUE)	
		return 2;
	
	
	r=sec_login_validate_identity(
	login_context,
	&password_record,
	&reset_password,
	&authorization_source,
	&s);
	
	if(reset_password==TRUE)
		return 3;	
	
		
	if(s!=error_status_ok || r!=TRUE)
		return 4;
	
	r=sec_login_certify_identity(
	login_context, 
	&s);
	
	if(s!=error_status_ok || r!=TRUE)
		return 5;
		
	sec_login_set_context(login_context,&s);
	
	if(s!=error_status_ok )
		return 6;
	
	return 0;	
}

int Dce_change_password(const char * principal_name, const char *password, const char * caller_password)
{
	error_status_t s = error_status_ok;
	sec_rgy_handle_t context;
	sec_rgy_login_name_t login_name, login_name_mask;
	sec_rgy_cursor_t account_cursor;
	sec_passwd_rec_t key_data, caller_key_data;
	sec_passwd_str_t  tmp_password, caller_tmp_password;
	sec_passwd_type_t key_type = sec_passwd_des; // required by sec_rgy_acct_passwd
	sec_passwd_version_t version;
	sec_rgy_sid_t sid;
	sec_rgy_unix_sid_t unix_sid;
	sec_rgy_acct_key_t key_part;
	sec_rgy_acct_user_t user_part;
	sec_rgy_acct_admin_t admin_part;
	unsigned char cell_name[100];
		
	key_data.key.tagged_union.plain=&(tmp_password[0]);
	caller_key_data.key.tagged_union.plain=&(caller_tmp_password[0]);
	
	key_data.version_number = sec_passwd_c_version_none;
	key_data.key.key_type = sec_passwd_plain;
	key_data.pepper = 0;
	
	caller_key_data.version_number = sec_passwd_c_version_none;
	caller_key_data.key.key_type = sec_passwd_plain;
	caller_key_data.pepper = 0;
			
	
	if(	strlen(principal_name) > sec_rgy_name_t_size - 1 || 
		strlen(password) > sec_passwd_str_max_len - 1 || 
		strlen(caller_password) > sec_passwd_str_max_len - 1
	  )
		return 1;
		
	memset(login_name_mask.pname,0,sec_rgy_name_t_size);
	memset(login_name_mask.gname,0,sec_rgy_name_t_size);
	memset(login_name_mask.oname,0,sec_rgy_name_t_size);
	strncpy((char*)login_name_mask.pname,principal_name,sec_rgy_name_t_size-1);
	
	memset(tmp_password,0,sec_passwd_str_max_len);
	strncpy((char*)tmp_password,password,sec_passwd_str_max_len - 1);

	memset(caller_tmp_password,0,sec_passwd_str_max_len);
	strncpy((char*)caller_tmp_password,caller_password,sec_passwd_str_max_len - 1);
		
	// local cell
	strcpy((char*)cell_name,"/.:");
	
	sec_rgy_site_open_update(
	cell_name,			
	&context,
	&s);
	
	if(s!=error_status_ok) return 2;
	
		// precaution, it is not used
	sec_rgy_cursor_reset(
	&account_cursor); 
		
		// need only login_name
	sec_rgy_acct_lookup(
	context,
	&login_name_mask,
	&account_cursor,
	&login_name,
	&sid,
	&unix_sid,
	&key_part,
	&user_part,
	&admin_part,
	&s);
	
	if(s!=error_status_ok) 
	{
		sec_rgy_site_close(
		context,
		&s);
	
		return 3;
	}
	
	
	sec_rgy_acct_passwd(
	context,
	&login_name,
	&caller_key_data,	
	&key_data,
	key_type,
	&version,
	&s);
	
	
	if(s!=error_status_ok) 
	{	
		sec_rgy_site_close(
		context,
		&s);
	
		return 4;
	}
	
	sec_rgy_site_close(
	context,
	&s);
	
	return 0;
}