/*
 *
 * From ENCRYPTION.txt for Samba release 2.0.6
 *	- LanManager encryption
 	LanManager encryption is somewhat similar to UNIX password
	encryption. The server uses a file containing a hashed value of a
	user's password.  This is created by taking the user's plaintext
	password, capitalising it, and either truncating to 14 bytes (or
	padding to 14 bytes with null bytes). This 14 byte value is used as
	two 56 bit DES keys to encrypt a 'magic' eight byte value, forming a
	16 byte value which is stored by the server and client. Let this value
	be known as the *hashed password*.

	- Windows NT encryption
	Windows NT encryption is a higher quality mechanism, consisting
	of doing an MD4 hash on a Unicode version of the user's password. This
	also produces a 16 byte hash value that is non-reversible.


 */

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>

#include "includes.h"

#undef strcpy
#undef strcat

#ifndef CONFIGFILE
#define CONFIGFILE "/etc/smb/smb.conf"
#endif

#ifdef _BSD_
extern char *sys_errlist[];
# define raise(s) kill(getpid(),(s))
# define strerror(e) sys_errlist[(e)]
#endif
extern char *optarg;
extern int optind, opterr, optopt;

void    usage(char *name);
void    fatalError(char *name,char *str);

void    usage(char *name)
{
    fprintf(stderr,
	"usage: %s [-c cpass] [-q] pass...\n",name);
	exit(-1);
}


main(int argc, char **argv, char **envp)
{
	unsigned char nt_p16[16], p16[16];
	char nt_p32[33], p32[33];
	char p[66];
	char *servicesf = CONFIGFILE;
	int i;


	int		option;
	int		quiet=0;
	int		compare=0;
	char	*pass;
	char	*cpass;

	struct timeval	tp;

	while(( option = getopt(argc, argv, "qc:s:h"))!=EOF )
	{
		switch(option)
		{
			case 'q':
				quiet=1;
				break;
			case 'c':
				compare=1;
				cpass=optarg;
				break;
			default:
				usage(argv[0]);
				break;
		}
	}

	memset(nt_p16, '\0', 16);
	memset(nt_p32, '\0', 33);
	memset(p16, '\0', 16);
	memset(p32, '\0', 33);

	TimeInit();
	charset_initialise();
	lp_load(servicesf,1,0,0);
	codepage_initialise(lp_client_code_page());

	nt_lm_owf_gen(argv[optind], nt_p16, p16);
	for( i = 0; i < 16; i++)
	{
		slprintf(&nt_p32[i*2], 3, "%02X", nt_p16[i]);
		slprintf(&p32[i*2], 3, "%02X", p16[i]);
	}
	strcpy(p,p32);
	strcat(p,":");
	strcat(p,nt_p32);

	if (argv[optind])
	{
		if (compare)
		{
			return(strcmp(cpass,p));
		}
		else
		{
			printf("%s\n", p);
			return (0);
		}
	}
	else
	{
		return(1);
	}
}