tree_cell *
nasl_ntlmv2_hash (lex_ctxt * lexic)
{
  const uchar *server_chal = (uchar *) get_str_var_by_name (lexic, "cryptkey");
  int sc_len = get_var_size_by_name (lexic, "cryptkey");
  const uchar *ntlm_v2_hash = (uchar *) get_str_var_by_name (lexic, "passhash");
  int hash_len = get_var_size_by_name (lexic, "passhash");
  int client_chal_length = get_int_var_by_name (lexic, "length", -1);
  tree_cell *retc;
  unsigned char ntlmv2_response[16];
  unsigned char *ntlmv2_client_data = NULL;
  unsigned char *final_response;
  int i;

  if (sc_len < 0 || server_chal == NULL || hash_len < 0 || ntlm_v2_hash == NULL
      || client_chal_length < 0)
    {
      nasl_perror (lexic,
                   "Syntax : ntlmv2_hash(cryptkey:<c>, passhash:<p>, length:<l>)\n");
      return NULL;
    }

  /* NTLMv2 */

  /* We also get to specify some random data */
  ntlmv2_client_data = emalloc (client_chal_length);
  for (i = 0; i < client_chal_length; i++)
    ntlmv2_client_data[i] = rand () % 256;



  assert (hash_len == 16);
  /* Given that data, and the challenge from the server, generate a response */
  SMBOWFencrypt_ntv2_ntlmssp(ntlm_v2_hash, server_chal, 8, ntlmv2_client_data,
                      client_chal_length, ntlmv2_response);

  /* put it into nt_response, for the code below to put into the packet */
  final_response = emalloc (client_chal_length + sizeof (ntlmv2_response));
  memcpy (final_response, ntlmv2_response, sizeof (ntlmv2_response));
  /* after the first 16 bytes is the random data we generated above, so the server can verify us with it */
  memcpy (final_response + sizeof (ntlmv2_response), ntlmv2_client_data,
          client_chal_length);

  efree (&ntlmv2_client_data);

  retc = alloc_tree_cell (0, NULL);
  retc->type = CONST_DATA;
  retc->size = client_chal_length + sizeof (ntlmv2_response);
  retc->x.str_val = (char *) final_response;

  return retc;
}
/*---------------------------------------------------------------------*/
tree_cell* nasl_crap(lex_ctxt* lexic)
{
  tree_cell	*retc;
  char		*data = get_str_local_var_by_name(lexic, "data");
  int		data_len = -1;
  int		len = get_int_local_var_by_name(lexic, "length", -1);
  int		len2 = get_int_var_by_num(lexic, 0, -1);


  if(len < 0 && len2 < 0)
    {
      nasl_perror(lexic, "crap: invalid or missing 'length' argument\n");
      return NULL;
    }
  if (len >= 0 && len2 >= 0)
    {
      nasl_perror(lexic, "crap: cannot set both unnamed and named 'length'\n");
      return NULL;
    }
  if (len < 0)
    len = len2;

  if( len == 0 )
  	return FAKE_CELL;
	
  if (data != NULL)
    {
      data_len = get_var_size_by_name(lexic, "data");
      if (data_len == 0)
	{
	  nasl_perror(lexic, "crap: invalid null 'data' parameter\n");
	  return NULL;
	}
    }

  retc = alloc_tree_cell(0, NULL);
  retc->type = CONST_DATA /*CONST_STR*/;
  retc->x.str_val = emalloc(len+1);
  retc->size = len;
  if (data == NULL)
    memset(retc->x.str_val, 'X', len);
  else
    {
      int	i,r;
      for(i = 0; i < len - data_len; i += data_len)
	memcpy(retc->x.str_val + i, data, data_len);
	
      if(data_len != 1)
       {
        if((r = (len % data_len)) > 0)
 	 memcpy(retc->x.str_val + (len - r), data, r);
	else
	 memcpy(retc->x.str_val + (len - data_len), data, data_len);
       }
      else 
         retc->x.str_val[ len - 1 ] = data[0];
    }
  retc->x.str_val[len] = '\0';
  return retc;
}
tree_cell *
nasl_ntlmv1_hash (lex_ctxt * lexic)
{
  const uchar *cryptkey = (uchar *) get_str_var_by_name (lexic, "cryptkey");
  char *password = get_str_var_by_name (lexic, "passhash");
  int pass_len = get_var_size_by_name (lexic, "passhash");
  unsigned char p21[21];
  tree_cell *retc;
  uchar *ret;

  if (cryptkey == NULL || password == NULL)
    {
      nasl_perror (lexic, "Syntax : ntlmv1_hash(cryptkey:<c>, passhash:<p>)\n");
      return NULL;
    }

  bzero (p21, sizeof (p21));
  memcpy (p21, password, pass_len < 16 ? pass_len : 16);

  ret = emalloc (24);

  E_P24 (p21, cryptkey, ret);
  retc = alloc_tree_cell (0, NULL);
  retc->type = CONST_DATA;
  retc->size = 24;
  retc->x.str_val = (char *) ret;

  return retc;
}
tree_cell *
nasl_send (lex_ctxt * lexic)
{
  int soc = get_int_local_var_by_name (lexic, "socket", 0);
  char *data = get_str_local_var_by_name (lexic, "data");
  int option = get_int_local_var_by_name (lexic, "option", 0);
  int length = get_int_local_var_by_name (lexic, "length", 0);
  int data_length = get_var_size_by_name (lexic, "data");
  int n;
  tree_cell *retc;
  int type;
  unsigned int type_len = sizeof (type);


  if (soc <= 0 || data == NULL)
    {
      nasl_perror (lexic, "Syntax error with the send() function\n");
      nasl_perror (lexic,
                   "Correct syntax is : send(socket:<soc>, data:<data>\n");
      return NULL;
    }

  if (length <= 0 || length > data_length)
    length = data_length;


  if (!fd_is_stream (soc)
      && getsockopt (soc, SOL_SOCKET, SO_TYPE, &type, &type_len) == 0
      && type == SOCK_DGRAM)
    {
      n = send (soc, data, length, option);
      add_udp_data (lexic->script_infos, soc, data, length);
    }
  else
    n = nsend (soc, data, length, option);

  retc = alloc_tree_cell (0, NULL);
  retc->type = CONST_INT;
  retc->x.i_val = n;

  return retc;
}
/**
 * @brief Write file
 */
tree_cell *
nasl_file_write (lex_ctxt * lexic)
{
  tree_cell *retc;
  char *content;
  int len;
  int fd;
  int n;

  content = get_str_local_var_by_name (lexic, "data");
  fd = get_int_local_var_by_name (lexic, "fp", -1);
  if (content == NULL || fd < 0)
    {
      nasl_perror (lexic, "file_write: need two arguments 'fp' and 'data'\n");
      return NULL;
    }
  len = get_var_size_by_name (lexic, "data");


  for (n = 0; n < len;)
    {
      int e;
      errno = 0;
      e = write (fd, content + n, len - n);
      if (e < 0 && errno == EINTR)
        continue;
      else if (e <= 0)
        {
          nasl_perror (lexic, "file_write: write() failed - %s\n",
                       strerror (errno));
          break;
        }
      else
        n += e;
    }



  retc = alloc_typed_cell (CONST_INT);
  retc->x.i_val = n;
  return retc;
}
tree_cell *
nasl_insert_hexzeros (lex_ctxt * lexic)
{
  const uchar *in = (uchar *) get_str_var_by_name (lexic, "in");
  int in_len = get_var_size_by_name (lexic, "in");
  char *src;
  smb_ucs2_t *out, *dst, val;
  int i;
  size_t byte_len;
  tree_cell *retc;
  if (in_len < 0 || in == NULL)
    {
      nasl_perror (lexic, "Syntax : insert_hexzeros(in:<i>)\n");
      return NULL;
    }

  byte_len = sizeof (smb_ucs2_t) * (strlen ((char *) in) + 1);
  out = emalloc (byte_len);
  dst = out;
  src = (char *) in;

  for (i = 0; i < in_len; i++)
    {
      val = *src;
      *dst = val;
      dst++;
      src++;
      if (val == 0)
        break;
    }


  /* We don't want null termination */
  byte_len = byte_len - 2;

  retc = alloc_tree_cell (0, NULL);
  retc->type = CONST_DATA;
  retc->size = byte_len;
  retc->x.str_val = (char *) out;
  return retc;
}
/* Does both the NTLMv2 owfs of a user's password */
tree_cell *
nasl_ntv2_owf_gen (lex_ctxt * lexic)
{
  const uchar *owf_in = (uchar *) get_str_var_by_name (lexic, "owf");
  int owf_in_len = get_var_size_by_name (lexic, "owf");
  char *user_in = get_str_var_by_name (lexic, "login");
  int user_in_len = get_var_size_by_name (lexic, "login");
  char *domain_in = get_str_var_by_name (lexic, "domain");
  int domain_len = get_var_size_by_name (lexic, "domain");
  char *src_user, *src_domain;
  smb_ucs2_t *user, *dst_user, val_user;
  smb_ucs2_t *domain, *dst_domain, val_domain;
  int i;
  size_t user_byte_len;
  size_t domain_byte_len;
  tree_cell *retc;
  uchar *kr_buf;
  HMACMD5Context ctx;

  if (owf_in_len < 0 || owf_in == NULL || user_in_len < 0 || user_in == NULL
      || domain_len < 0 || domain_in == NULL)
    {
      nasl_perror (lexic,
                   "Syntax : ntv2_owf_gen(owf:<o>, login:<l>, domain:<d>)\n");
      return NULL;
    }

  assert (owf_in_len == 16);

  user_byte_len = sizeof (smb_ucs2_t) * (strlen (user_in) + 1);
  user = emalloc (user_byte_len);
  dst_user = user;
  src_user = user_in;

  for (i = 0; i < user_in_len; i++)
    {
      val_user = *src_user;
      *dst_user = val_user;
      dst_user++;
      src_user++;
      if (val_user == 0)
        break;
    }

  domain_byte_len = sizeof (smb_ucs2_t) * (strlen (domain_in) + 1);
  domain = emalloc (domain_byte_len);
  dst_domain = domain;
  src_domain = domain_in;

  for (i = 0; i < domain_len; i++)
    {
      val_domain = *src_domain;
      *dst_domain = val_domain;

      dst_domain++;
      src_domain++;
      if (val_domain == 0)
        break;
    }

  strupper_w (user);
  strupper_w (domain);

  assert (user_byte_len >= 2);
  assert (domain_byte_len >= 2);

  /* We don't want null termination */
  user_byte_len = user_byte_len - 2;
  domain_byte_len = domain_byte_len - 2;

  kr_buf = emalloc (16);

  hmac_md5_init_limK_to_64 (owf_in, 16, &ctx);
  hmac_md5_update ((const unsigned char *) user, user_byte_len, &ctx);
  hmac_md5_update ((const unsigned char *) domain, domain_byte_len, &ctx);
  hmac_md5_final (kr_buf, &ctx);

  efree (&user);
  efree (&domain);

  retc = alloc_tree_cell (0, NULL);
  retc->type = CONST_DATA;
  retc->size = 16;
  retc->x.str_val = (char *) kr_buf;

  return retc;
}
/**
 * @brief Write file
 */
tree_cell *
nasl_fwrite (lex_ctxt * lexic)
{
  tree_cell *retc;
  char *content, *fname;
  struct stat lstat_info, fstat_info;
  int fd;
  int len, i, x;
  FILE *fp;

  content = get_str_local_var_by_name (lexic, "data");
  fname = get_str_local_var_by_name (lexic, "file");
  if (content == NULL || fname == NULL)
    {
      nasl_perror (lexic, "fwrite: need two arguments 'data' and 'file'\n");
      return NULL;
    }
  len = get_var_size_by_name (lexic, "data");

  if (lstat (fname, &lstat_info) == -1)
    {
      if (errno != ENOENT)
        {
          nasl_perror (lexic, "fwrite: %s: %s\n", fname, strerror (errno));
          return NULL;
        }
      fd = open (fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
      if (fd < 0)
        {
          nasl_perror (lexic, "fwrite: %s: %s\n", fname, strerror (errno));
          return NULL;
        }
    }
  else
    {
      fd = open (fname, O_WRONLY | O_CREAT, 0600);
      if (fd < 0)
        {
          nasl_perror (lexic, "fwrite: %s: possible symlink attack!?! %s\n",
                       fname, strerror (errno));
          return NULL;
        }
      if (fstat (fd, &fstat_info) == -1)
        {
          close (fd);
          nasl_perror (lexic, "fwrite: %s: possible symlink attack!?! %s\n",
                       fname, strerror (errno));
          return NULL;
        }
      else
        {
          if (lstat_info.st_mode != fstat_info.st_mode
              || lstat_info.st_ino != fstat_info.st_ino
              || lstat_info.st_dev != fstat_info.st_dev)
            {
              close (fd);
              nasl_perror (lexic, "fwrite: %s: possible symlink attack!?!\n",
                           fname);
              return NULL;
            }
        }
    }
  if (ftruncate (fd, 0) == -1)
    {
      close (fd);
      nasl_perror (lexic, "fwrite: %s: %s\n", fname, strerror (errno));
      return NULL;
    }
  fp = fdopen (fd, "w");
  if (fp == NULL)
    {
      close (fd);
      nasl_perror (lexic, "fwrite: %s: %s\n", fname, strerror (errno));
      return NULL;
    }

  for (i = 0; i < len;)
    {
      x = fwrite (content + i, 1, len - i, fp);
      if (x > 0)
        i += x;
      else
        {
          nasl_perror (lexic, "fwrite: %s: %s\n", fname, strerror (errno));
          (void) fclose (fp);
          unlink (fname);
          return NULL;
        }
    }

  if (fclose (fp) < 0)
    {
      nasl_perror (lexic, "fwrite: %s: %s\n", fname, strerror (errno));
      unlink (fname);
      return NULL;
    }
  retc = alloc_typed_cell (CONST_INT);
  retc->x.i_val = len;
  return retc;
}
tree_cell*
nasl_split(lex_ctxt* lexic)
{
  tree_cell	*retc;
  nasl_array	*a;
  char		*p, *str, *sep;
  int		i, i0, j, len, sep_len = 0, keep = 1;
  anon_nasl_var	v;


  str = get_str_var_by_num(lexic, 0);
  if (str == NULL)
    return NULL;
  len = get_var_size_by_num(lexic, 0);
  sep = get_str_local_var_by_name(lexic, "sep");
  if (sep != NULL)
    sep_len = get_var_size_by_name(lexic, "sep");
  keep = get_int_local_var_by_name(lexic, "keep", 1);

  retc = alloc_tree_cell(0, NULL);
  retc->type = DYN_ARRAY;
  retc->x.ref_val = a = emalloc(sizeof(nasl_array));

  bzero(&v, sizeof(v));
  v.var_type = VAR2_DATA;
  
  if (sep !=  NULL)
    {
      i = 0; j = 0;
      for(;;)
	{
	  if ((p = (char*)memmem(str + i, len - i, sep, sep_len)) == NULL)
	    {
	      v.v.v_str.s_siz = len - i;
	      v.v.v_str.s_val = str + i;
	      (void) add_var_to_list(a, j ++, &v);
	      return retc;
	    }
	  else
	    {
	      if (keep)
		v.v.v_str.s_siz = (p - (str + i)) + sep_len;
	      else
		v.v.v_str.s_siz = p - (str + i); 
	      v.v.v_str.s_val = str + i;
	      (void) add_var_to_list(a, j ++, &v);
	      i = (p - str) + sep_len;
	      if (i >= len)
		return retc;
	    }
	}
    }
  
  /* Otherwise, we detect the end of line. A little more subtle */
  for (i = i0 = j = 0; i < len; i ++)
    {
      if (str[i] == '\r' && str[i+1] == '\n')
	{
	  i ++;
	  if (keep)
	    v.v.v_str.s_siz = i - i0 + 1;
	  else
	    v.v.v_str.s_siz = i - i0 - 1;
	  v.v.v_str.s_val = str + i0;
	  i0 = i + 1;
	  (void) add_var_to_list(a, j ++, &v);
	}
      else if (str[i] == '\n')
	{
	  if (keep)
	    v.v.v_str.s_siz = i - i0 + 1;
	  else
	    v.v.v_str.s_siz = i - i0;
	  v.v.v_str.s_val = str + i0;
	  i0 = i + 1;
	  (void) add_var_to_list(a, j ++, &v);
	}
    }

  if (i > i0)
    {
      v.v.v_str.s_siz = i - i0;
      v.v.v_str.s_val = str + i0;
      (void) add_var_to_list(a, j ++, &v);
    }
  return retc;
}
/*
 * regex syntax :
 *
 *	egrep(pattern, string)
 */
tree_cell * nasl_egrep(lex_ctxt * lexic)
{
 char * pattern = get_str_local_var_by_name(lexic, "pattern");
 char * string = get_str_local_var_by_name(lexic, "string");
 int icase = get_int_local_var_by_name(lexic, "icase", 0);
 tree_cell * retc;
 regex_t re;
 regmatch_t subs[NS];
 char * s, * t;
 int copt;
 char * rets;
 int max_size = get_var_size_by_name(lexic, "string");
 
 if(pattern == NULL || string == NULL)
  return NULL;
  
 bzero(subs, sizeof(subs));
 bzero(&re, sizeof(re));
  
  if(icase != 0)
  	copt = REG_ICASE;
  else 
  	copt = 0;
	
  rets = emalloc(max_size + 1);
  string = estrdup(string);
  
  
  s = string;
  while( s[0] == '\n' )s++;
  
  t = strchr(s, '\n');
  if(t != NULL ) 
  	t[0] = '\0';
  
  if(s[0] != '\0')
   for(;;)
   {
   bzero(&re, sizeof(re));
   nasl_re_set_syntax(RE_SYNTAX_POSIX_EGREP);
   if(nasl_regcomp(&re, pattern, REG_EXTENDED|copt))
   {
   nasl_perror(lexic, "egrep() : regcomp() failed\n");
   return NULL;
   }
  
   
   if(nasl_regexec(&re, s, (size_t)NS, subs, 0) == 0)
     {
      char * t = strchr(s, '\n');
      
      if(t != NULL)
      	t[0]='\0';
	
      strcat(rets, s);
      strcat(rets, "\n");
      if(t != NULL)
      	t[0]='\n';
    }
  
  nasl_regfree(&re);
  
  if(t == NULL)
  	s = NULL;
  else  
   	s = &(t[1]);
 
  if(s != NULL )
  	{
	while(s[0] == '\n') s++; /* Skip empty lines */
  	t = strchr(s, '\n');
	}
  else 
  	t = NULL;
	
  if(t != NULL)
  	t[0] = '\0';
	
  if(s == NULL || s[0] == '\0')break;
  }
#ifdef I_WANT_MANY_DIRTY_ERROR_MESSAGES  
  if(rets[0] == '\0')
  {
   efree(&rets);
   efree(&string);
   return FAKE_CELL;
  }
#endif
  efree(&string);
  
  retc = alloc_tree_cell(0, NULL);
  retc->type = CONST_DATA;
  retc->size = strlen(rets);
  retc->x.str_val = rets;
 
  return retc;
}