Beispiel #1
0
/* Send the first key exchange message ( g, n, s) and append the verifier algorithm number 
 * Data is allocated by the caller, and should have data_size size.
 */
int
_gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data)
{
  int ret;
  uint8_t *data_n, *data_s;
  uint8_t *data_g;
  char *username;
  SRP_PWD_ENTRY *pwd_entry;
  srp_server_auth_info_t info;
  ssize_t data_size;
  size_t n_b, tmp_size;
  char buf[64];
  uint8_t *data_b;

  if ((ret =
       _gnutls_auth_info_set (session, GNUTLS_CRD_SRP,
			      sizeof (srp_server_auth_info_st), 1)) < 0)
    {
      gnutls_assert ();
      return ret;
    }

  info = _gnutls_get_auth_info (session);
  username = info->username;

  _gnutls_str_cpy (username, MAX_SRP_USERNAME,
		   session->security_parameters.extensions.srp_username);

  ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry);

  if (ret < 0)
    {
      gnutls_assert ();
      return ret;
    }

  /* copy from pwd_entry to local variables (actually in session) */
  tmp_size = pwd_entry->g.size;
  if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, &tmp_size) < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  tmp_size = pwd_entry->n.size;
  if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, &tmp_size) < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  tmp_size = pwd_entry->v.size;
  if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, &tmp_size) < 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_SCAN_FAILED;
    }

  /* Calculate:  B = (k*v + g^b) % N 
   */
  B = _gnutls_calc_srp_B (&_b, G, N, V);
  if (B == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  if (_gnutls_mpi_print (NULL, &n_b, B) != 0)
    {
      gnutls_assert ();
      return GNUTLS_E_MPI_PRINT_FAILED;
    }


  /* Allocate size to hold the N, g, s, B 
   */

  data_size = (pwd_entry->n.size + 2 + pwd_entry->g.size + 2 +
	       pwd_entry->salt.size + 1) + (n_b + 2);

  (*data) = gnutls_malloc (data_size);
  if ((*data) == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }

  /* copy N (mod n) 
   */
  data_n = *data;
  _gnutls_write_datum16 (data_n, pwd_entry->n);


  /* copy G (generator) to data 
   */
  data_g = &data_n[2 + pwd_entry->n.size];
  _gnutls_write_datum16 (data_g, pwd_entry->g);


  /* copy the salt 
   */
  data_s = &data_g[2 + pwd_entry->g.size];
  _gnutls_write_datum8 (data_s, pwd_entry->salt);


  /* Copy the B value
   */

  data_b = &data_s[1 + pwd_entry->salt.size];
  if (_gnutls_mpi_print (&data_b[2], &n_b, B) != 0) 
    {
      gnutls_assert();
      return GNUTLS_E_MPI_PRINT_FAILED;
    }

  _gnutls_write_uint16 (n_b, data_b);

  _gnutls_hard_log ("INT: SRP B[%d]: %s\n", n_b,
		    _gnutls_bin2hex (&data_b[2], n_b, buf, sizeof (buf)));

  _gnutls_srp_entry_free (pwd_entry);

  return data_size;
}
Beispiel #2
0
int
_gnutls_srp_pwd_read_entry (gnutls_session_t state, char *username,
                            SRP_PWD_ENTRY ** _entry)
{
  gnutls_srp_server_credentials_t cred;
  FILE *fd;
  char line[2 * 1024];
  unsigned i, len;
  int ret;
  int idx, last_idx;
  SRP_PWD_ENTRY *entry;

  *_entry = gnutls_calloc (1, sizeof (SRP_PWD_ENTRY));
  if (*_entry == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_MEMORY_ERROR;
    }
  entry = *_entry;

  cred = (gnutls_srp_server_credentials_t)
    _gnutls_get_cred (state->key, GNUTLS_CRD_SRP, NULL);
  if (cred == NULL)
    {
      gnutls_assert ();
      _gnutls_srp_entry_free (entry);
      return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
    }

  /* if the callback which sends the parameters is
   * set, use it.
   */
  if (cred->pwd_callback != NULL)
    {
      ret = cred->pwd_callback (state, username, &entry->salt,
                                &entry->v, &entry->g, &entry->n);

      if (ret == 1)
        {                       /* the user does not exist */
          if (entry->g.size != 0 && entry->n.size != 0)
            {
              ret = _randomize_pwd_entry (entry);
              if (ret < 0)
                {
                  gnutls_assert ();
                  _gnutls_srp_entry_free (entry);
                  return ret;
                }
              return 0;
            }
          else
            {
              gnutls_assert ();
              ret = -1;         /* error in the callback */
            }
        }

      if (ret < 0)
        {
          gnutls_assert ();
          _gnutls_srp_entry_free (entry);
          return GNUTLS_E_SRP_PWD_ERROR;
        }

      return 0;
    }

  /* The callback was not set. Proceed.
   */

  if (cred->password_file == NULL)
    {
      gnutls_assert ();
      return GNUTLS_E_SRP_PWD_ERROR;
    }

  /* Open the selected password file.
   */
  fd = fopen (cred->password_file, "r");
  if (fd == NULL)
    {
      gnutls_assert ();
      _gnutls_srp_entry_free (entry);
      return GNUTLS_E_SRP_PWD_ERROR;
    }

  last_idx = 1;                 /* a default value */

  len = strlen (username);
  while (fgets (line, sizeof (line), fd) != NULL)
    {
      /* move to first ':' */
      i = 0;
      while ((line[i] != ':') && (line[i] != '\0') && (i < sizeof (line)))
        {
          i++;
        }

      if (strncmp (username, line, MAX (i, len)) == 0)
        {
          if ((idx = pwd_put_values (entry, line)) >= 0)
            {
              /* Keep the last index in memory, so we can retrieve fake parameters (g,n)
               * when the user does not exist.
               */
              /* XXX: last_idx will not be read as both if block branches return. */
              last_idx = idx;
              if (pwd_read_conf (cred->password_conf_file, entry, idx) == 0)
                {
                  return 0;
                }
              else
                {
                  gnutls_assert ();
                  _gnutls_srp_entry_free (entry);
                  return GNUTLS_E_SRP_PWD_ERROR;
                }
            }
          else
            {
              gnutls_assert ();
              _gnutls_srp_entry_free (entry);
              return GNUTLS_E_SRP_PWD_ERROR;
            }
        }
    }

  /* user was not found. Fake him. Actually read the g,n values from
   * the last index found and randomize the entry.
   */
  if (pwd_read_conf (cred->password_conf_file, entry, last_idx) == 0)
    {
      ret = _randomize_pwd_entry (entry);
      if (ret < 0)
        {
          gnutls_assert ();
          _gnutls_srp_entry_free (entry);
          return ret;
        }

      return 0;
    }

  gnutls_assert ();
  _gnutls_srp_entry_free (entry);
  return GNUTLS_E_SRP_PWD_ERROR;

}
Beispiel #3
0
/* Send the first key exchange message ( g, n, s) and append the verifier algorithm number 
 * Data is allocated by the caller, and should have data_size size.
 */
int
_gnutls_gen_srp_server_kx(gnutls_session_t session,
			  gnutls_buffer_st * data)
{
	int ret;
	char *username;
	SRP_PWD_ENTRY *pwd_entry;
	srp_server_auth_info_t info;
	size_t tmp_size;
	extension_priv_data_t epriv;
	srp_ext_st *priv;

	ret =
	    _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SRP,
					 &epriv);
	if (ret < 0) {		/* peer didn't send a username */
		gnutls_assert();
		return GNUTLS_E_UNKNOWN_SRP_USERNAME;
	}
	priv = epriv;

	if ((ret =
	     _gnutls_auth_info_set(session, GNUTLS_CRD_SRP,
				   sizeof(srp_server_auth_info_st),
				   1)) < 0) {
		gnutls_assert();
		return ret;
	}

	info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP);
	if (info == NULL)
		return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);

	username = info->username;

	_gnutls_str_cpy(username, MAX_USERNAME_SIZE, priv->username);

	ret = _gnutls_srp_pwd_read_entry(session, username, &pwd_entry);

	if (ret < 0) {
		gnutls_assert();
		return ret;
	}

	/* copy from pwd_entry to local variables (actually in session) */
	tmp_size = pwd_entry->g.size;
	if (_gnutls_mpi_init_scan_nz(&G, pwd_entry->g.data, tmp_size) < 0) {
		gnutls_assert();
		ret = GNUTLS_E_MPI_SCAN_FAILED;
		goto cleanup;
	}

	tmp_size = pwd_entry->n.size;
	if (_gnutls_mpi_init_scan_nz(&N, pwd_entry->n.data, tmp_size) < 0) {
		gnutls_assert();
		ret = GNUTLS_E_MPI_SCAN_FAILED;
		goto cleanup;
	}

	tmp_size = pwd_entry->v.size;
	if (_gnutls_mpi_init_scan_nz(&V, pwd_entry->v.data, tmp_size) < 0) {
		gnutls_assert();
		ret = GNUTLS_E_MPI_SCAN_FAILED;
		goto cleanup;
	}

	/* Calculate:  B = (k*v + g^b) % N 
	 */
	B = _gnutls_calc_srp_B(&_b, G, N, V);
	if (B == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_MEMORY_ERROR;
		goto cleanup;
	}

	/* copy N (mod n) 
	 */
	ret =
	    _gnutls_buffer_append_data_prefix(data, 16, pwd_entry->n.data,
					      pwd_entry->n.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* copy G (generator) to data 
	 */
	ret =
	    _gnutls_buffer_append_data_prefix(data, 16, pwd_entry->g.data,
					      pwd_entry->g.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* copy the salt 
	 */
	ret =
	    _gnutls_buffer_append_data_prefix(data, 8,
					      pwd_entry->salt.data,
					      pwd_entry->salt.size);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	/* Copy the B value
	 */

	ret = _gnutls_buffer_append_mpi(data, 16, B, 0);
	if (ret < 0) {
		gnutls_assert();
		goto cleanup;
	}

	_gnutls_mpi_log("SRP B: ", B);

	ret = data->length;

      cleanup:
	_gnutls_srp_entry_free(pwd_entry);
	return ret;
}
Beispiel #4
0
int
_gnutls_srp_pwd_read_entry(gnutls_session_t state, char *username,
			   SRP_PWD_ENTRY ** _entry)
{
	gnutls_srp_server_credentials_t cred;
	FILE *fd = NULL;
	char *line = NULL;
	size_t line_size = 0;
	unsigned i, len;
	int ret;
	int idx;
	SRP_PWD_ENTRY *entry = NULL;

	*_entry = gnutls_calloc(1, sizeof(SRP_PWD_ENTRY));
	if (*_entry == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}
	entry = *_entry;

	cred = (gnutls_srp_server_credentials_t)
	    _gnutls_get_cred(state, GNUTLS_CRD_SRP);
	if (cred == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_INSUFFICIENT_CREDENTIALS;
		goto cleanup;
	}

	/* if the callback which sends the parameters is
	 * set, use it.
	 */
	if (cred->pwd_callback != NULL) {
		ret = cred->pwd_callback(state, username, &entry->salt,
					 &entry->v, &entry->g, &entry->n);

		if (ret == 1) {	/* the user does not exist */
			if (entry->g.size != 0 && entry->n.size != 0) {
				ret = _randomize_pwd_entry(entry, cred, username);
				if (ret < 0) {
					gnutls_assert();
					goto cleanup;
				}
				return 0;
			} else {
				gnutls_assert();
				ret = -1;	/* error in the callback */
			}
		}

		if (ret < 0) {
			gnutls_assert();
			ret = GNUTLS_E_SRP_PWD_ERROR;
			goto cleanup;
		}

		return 0;
	}

	/* The callback was not set. Proceed.
	 */

	if (cred->password_file == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_SRP_PWD_ERROR;
		goto cleanup;
	}

	/* Open the selected password file.
	 */
	fd = fopen(cred->password_file, "r");
	if (fd == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_SRP_PWD_ERROR;
		goto cleanup;
	}

	len = strlen(username);
	while (getline(&line, &line_size, fd) > 0) {
		/* move to first ':' */
		i = 0;
		while ((i < line_size) && (line[i] != '\0')
		       && (line[i] != ':')) {
			i++;
		}

		if (strncmp(username, line, MAX(i, len)) == 0) {
			if ((idx = parse_tpasswd_values(entry, line)) >= 0) {
				/* Keep the last index in memory, so we can retrieve fake parameters (g,n)
				 * when the user does not exist.
				 */
				if (pwd_read_conf
				    (cred->password_conf_file, entry,
				     idx) == 0) {
					ret = 0;
					goto found;
				} else {
					gnutls_assert();
					ret = GNUTLS_E_SRP_PWD_ERROR;
					goto cleanup;
				}
			} else {
				gnutls_assert();
				ret = GNUTLS_E_SRP_PWD_ERROR;
				goto cleanup;
			}
		}
	}

	/* user was not found. Fake him. Actually read the g,n values from
	 * the last index found and randomize the entry.
	 */
	if (pwd_read_conf(cred->password_conf_file, entry, 1) == 0) {
		ret = _randomize_pwd_entry(entry, cred, username);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = 0;
		goto found;
	}

	ret = GNUTLS_E_SRP_PWD_ERROR;

cleanup:
	gnutls_assert();
	_gnutls_srp_entry_free(entry);

found:
	zeroize_key(line, line_size);
	free(line);
	if (fd)
		fclose(fd);
	return ret;
}