// Fix for john the ripper 1.6.37 by Sun-Zero, 2004. 07. 26.
/*
 * This file is part of John the Ripper password cracker,
 * Copyright (c) 1996-98 by Solar Designer
 */

#include <string.h>

#include "misc.h"
#include "formats.h"
#include "common.h"

#include "sha.h"
#include "base64.h"

#define FORMAT_LABEL			"nsldap"
#define FORMAT_NAME			"Netscape LDAP SHA"
#define SHA_TYPE                        "sha1"

#define BENCHMARK_COMMENT		""
#define BENCHMARK_LENGTH		-1

#define PLAINTEXT_LENGTH		72
#define CIPHERTEXT_LENGTH		33

#define BINARY_SIZE			20
#define SALT_SIZE			0

#define MIN_KEYS_PER_CRYPT		1
#define MAX_KEYS_PER_CRYPT		1

#define NSLDAP_MAGIC "{sha}"
#define NSLDAP_MAGIC_LENGTH 5

static struct fmt_tests tests[] = {
  {"{SHA}cMiB1KJphN3OeV9vcYF8nPRIDnk=", "aaaa"},  
  {"{SHA}iu0TIuVFC62weOH7YKgXod8loso=", "bbbb"},  
  {"{SHA}0ijZPTcJXMa+t2XnEbEwSOkvQu0=", "ccccccccc"},  
  {"{SHA}vNR9eUfJfcKmdkLDqNoKagho+qU=", "dddddddddd"},  
  {NULL}
};

static char crypt_key[BINARY_SIZE];
static char saved_key[PLAINTEXT_LENGTH + 1];

static void *
binary(char *ciphertext) {
  static char realcipher[BINARY_SIZE];

  base64_decode(NSLDAP_MAGIC_LENGTH+ciphertext, CIPHERTEXT_LENGTH, realcipher);
  return (void *)realcipher;
}

static int 
valid(char *ciphertext)
{
  if(ciphertext && strlen(ciphertext) == CIPHERTEXT_LENGTH)
    return !strncasecmp(ciphertext, NSLDAP_MAGIC, NSLDAP_MAGIC_LENGTH);
  return 0;
}

static int binary_hash_0(void *binary)
{
  return ((int *)binary)[0] & 0xF;
}

static int binary_hash_1(void *binary)
{
  return ((int *)binary)[0] & 0xFF;
}

static int binary_hash_2(void *binary)
{
  return ((int *)binary)[0] & 0xFFF;
}

static int get_hash_0(int index)
{
  return ((int *)crypt_key)[0] & 0xF;
}

static int get_hash_1(int index)
{
  return ((int *)crypt_key)[0] & 0xFF;
}

static int get_hash_2(int index)
{
  return ((int *)crypt_key)[0] & 0xFFF;
}

static void set_key(char *key, int index)
{
  strnzcpy(saved_key, key, PLAINTEXT_LENGTH+1);
}

static char *get_key(int index)
{
  return saved_key;
}

static int 
cmp_all(void *binary, int index)
{
  return !memcmp(binary, crypt_key, BINARY_SIZE);
}

static int 
cmp_exact(char *source, int index)
{
  return 1;
}

static void set_salt(void *salt) {
}

static void
crypt_all(int count) {  
  static SHA_CTX ctx;

  SHA1_Init(&ctx);
  SHA1_Update(&ctx, saved_key, strlen(saved_key));
  SHA1_Final(crypt_key, &ctx);
}

struct fmt_main fmt_NSLDAP = {
  {
    FORMAT_LABEL,
    FORMAT_NAME,
    SHA_TYPE,
    BENCHMARK_COMMENT,
    BENCHMARK_LENGTH,
    PLAINTEXT_LENGTH,
    BINARY_SIZE,
    SALT_SIZE,
    MIN_KEYS_PER_CRYPT,
    MAX_KEYS_PER_CRYPT,
    FMT_CASE | FMT_8_BIT,
    tests
  }, {
    fmt_default_init,
    valid,
    fmt_default_split,
    binary,
    fmt_default_salt,
    {
      binary_hash_0,
      binary_hash_1,
      binary_hash_2
    },
	fmt_default_salt_hash,
	set_salt,
	set_key,
	get_key,
	fmt_default_clear_keys,
	crypt_all, 
	{
	  get_hash_0,
	  get_hash_1,
	  get_hash_2
	},
	    cmp_all,
	    cmp_all,
	    cmp_exact
  }
};

