Exemplo n.º 1
0
static int _sx_sasl_rio(sx_t s, sx_plugin_t p, sx_buf_t buf) {
    sx_error_t sxe;
    int len, ret;
    char *out;
    Gsasl_session *sd = (Gsasl_session *) s->plugin_data[p->index];

    _sx_debug(ZONE, "doing sasl decode");

    /* decode the input */
    ret = gsasl_decode(sd, buf->data, buf->len, &out, &len);
    if (ret != GSASL_OK) {
        _sx_debug(ZONE, "gsasl_decode failed (%d): %s", ret, gsasl_strerror (ret));
        /* Fatal error */
        _sx_gen_error(sxe, SX_ERR_AUTH, "SASL Stream decoding failed", (char*) gsasl_strerror (ret));
        _sx_event(s, event_ERROR, (void *) &sxe);
        return -1;
    }
    
    /* replace the buffer */
    _sx_buffer_set(buf, out, len, NULL);
    free(out);

    _sx_debug(ZONE, "%d bytes decoded from sasl channel", len);
    
    return 1;
}
Exemplo n.º 2
0
static void
smtp (FILE * fh, Gsasl * ctx)
{
  char *line = NULL;
  size_t n = 0;
  int rc;

  print (fh, "220 localhost ESMTP GNU SASL smtp-server\n");

  while (gettrimline (&line, &n, fh) >= 0)
    {
      if (strncmp (line, "EHLO ", 5) == 0 || strncmp (line, "ehlo ", 5) == 0)
	{
	  char *mechlist;

	  rc = gsasl_server_mechlist (ctx, &mechlist);
	  if (rc != GSASL_OK)
	    {
	      print (fh, "221 localhost gsasl_server_mechlist (%d): %s\n",
		     rc, gsasl_strerror (rc));
	      goto done;
	    }

	  print (fh, "250-localhost\n");
	  print (fh, "250 AUTH %s\n", mechlist);

	  gsasl_free (mechlist);
	}
      else if (strncmp (line, "AUTH ", 5) == 0
	       || strncmp (line, "auth ", 5) == 0)
	{
	  Gsasl_session *session = NULL;

	  if ((rc = gsasl_server_start (ctx, line + 5, &session)) != GSASL_OK)
	    {
	      print (fh, "221 localhost gsasl_server_start (%d): %s\n",
		     rc, gsasl_strerror (rc));
	      goto done;
	    }

	  server_auth (fh, session);

	  gsasl_finish (session);
	}
      else if (strncmp (line, "QUIT", 4) == 0
	       || strncmp (line, "quit", 4) == 0)
	{
	  print (fh, "221 localhost QUIT\n");
	  goto done;
	}
      else
	print (fh, "500 unrecognized command\n");
    }

  print (fh, "221 localhost getline failure\n");

done:
  free (line);
}
Exemplo n.º 3
0
void
doit (void)
{
  const char *md5file;
  char key[BUFSIZ];
  size_t keylen = BUFSIZ - 1;
  int res;

  md5file = getenv ("MD5FILE");
  if (md5file)
    {
      char *p;
      if ((p = strchr (md5file, '=')))
	md5file = p;
    }

  if (!md5file)
    md5file = "cram-md5.pwd";

  keylen = sizeof (key) - 1;
  res = gsasl_md5pwd_get_password ("non-existing-file", "user", key, &keylen);
  if (res == GSASL_FOPEN_ERROR)
    success ("non-existing-file OK\n");
  else
    fail ("non-existing-file FAIL (%d): %s\n", res, gsasl_strerror (res));

  keylen = sizeof (key) - 1;
  res = gsasl_md5pwd_get_password (md5file, BILL, key, &keylen);
  if (res == GSASL_OK)
    success ("user-found OK\n");
  else
    fail ("user-found FAIL (%d): %s\n", res, gsasl_strerror (res));
  if (keylen != strlen (BILL_PASSWD)
      || memcmp (key, BILL_PASSWD, keylen) != 0)
    fail ("user-password FAIL (%lu): %.*s\n",
	  (unsigned long) keylen, (int) keylen, key);
  else
    success ("user-password OK\n");

  keylen = 5;
  res = gsasl_md5pwd_get_password (md5file, BILL, key, &keylen);
  if (res == GSASL_TOO_SMALL_BUFFER)
    success ("too-small-buffer OK\n");
  else
    fail ("too-small-buffer FAIL (%d): %s\n", res, gsasl_strerror (res));

  keylen = sizeof (key) - 1;
  res = gsasl_md5pwd_get_password (md5file, "user", key, &keylen);
  if (res == GSASL_AUTHENTICATION_ERROR)
    success ("no-such-user OK\n");
  else
    fail ("no-such-user FAIL (%d): %s\n", res, gsasl_strerror (res));
}
Exemplo n.º 4
0
void
register_sasl()
{
  int rc;
  char *listmech;
  struct wordsplit ws;
  
  if (!sasl_enable || init_sasl_0())
      return;
  rc =  gsasl_server_mechlist(ctx, &listmech);
  if (rc != GSASL_OK) {
      dico_log(L_ERR, 0, _("cannot get list of available SASL mechanisms: "
			   "%s"),
	       gsasl_strerror (rc));
      return;
  }

  if (wordsplit(listmech, &ws,
		WRDSF_NOVAR | WRDSF_NOCMD | WRDSF_SQUEEZE_DELIMS) == 0) {
      int i;
      for (i = 0; i < ws.ws_wordc; i++) {
	  if (!disabled_mechanism_p(ws.ws_wordv[i])) {
	      char *name = xdico_sasl_mech_to_capa(ws.ws_wordv[i]);
	      dicod_capa_register(name, NULL, init_sasl_1, NULL);
	      dicod_capa_add(name);
	  }
      }
      wordsplit_free(&ws);
  }
  free(listmech);
}
Exemplo n.º 5
0
static void
client (Gsasl * ctx)
{
  Gsasl_session *session;
  const char *mech = "PLAIN";
  int rc;

  /* Create new authentication session. */
  if ((rc = gsasl_client_start (ctx, mech, &session)) != GSASL_OK)
    {
      printf ("Cannot initialize client (%d): %s\n", rc, gsasl_strerror (rc));
      return;
    }

  /* Set username and password in session handle.  This info will be
     lost when this session is deallocated below.  */
  gsasl_property_set (session, GSASL_AUTHID, "jas");
  gsasl_property_set (session, GSASL_PASSWORD, "secret");

  /* Do it. */
  client_authenticate (session);

  /* Cleanup. */
  gsasl_finish (session);
}
Exemplo n.º 6
0
void
doit (void)
{
  const char *md5file;
  char *key;
  int res;

  md5file = getenv ("MD5FILE");
  if (md5file)
    {
      char *p;
      if ((p = strchr (md5file, '=')))
	md5file = p;
    }

  if (!md5file)
    md5file = "cram-md5.pwd";

  res = gsasl_simple_getpass ("non-existing-file", "user", &key);
  if (res == GSASL_AUTHENTICATION_ERROR)
    success ("non-existing-file OK\n");
  else
    fail ("non-existing-file FAIL (%d): %s\n", res, gsasl_strerror (res));

  res = gsasl_simple_getpass (md5file, BILL, &key);
  if (res == GSASL_OK)
    success ("user-found OK\n");
  else
    fail ("user-found FAIL (%d): %s\n", res, gsasl_strerror (res));
  if (strcmp (key, BILL_PASSWD) != 0)
    fail ("user-password FAIL: %s\n", key);
  else
    success ("user-password OK\n");
  if (res == GSASL_OK)
    gsasl_free (key);

  res = gsasl_simple_getpass (md5file, "user", &key);
  if (res == GSASL_AUTHENTICATION_ERROR)
    success ("no-such-user OK\n");
  else
    fail ("no-such-user FAIL (%d): %s\n", res, gsasl_strerror (res));
}
Exemplo n.º 7
0
static int
init_sasl_0()
{
    int rc = gsasl_init(&ctx);
    if (rc != GSASL_OK) {
	dico_log(L_ERR, 0, _("cannot initialize libgsasl: %s"),
		 gsasl_strerror(rc));
	return 1;
    }
    gsasl_callback_set(ctx, callback);
    return 0;
}
Exemplo n.º 8
0
static void
client_authenticate (Gsasl_session * session)
{
  char buf[BUFSIZ] = "";
  char *p;
  int rc;

  /* This loop mimics a protocol where the client send data first. */

  do
    {
      /* Generate client output. */
      rc = gsasl_step64 (session, buf, &p);

      if (rc == GSASL_NEEDS_MORE || rc == GSASL_OK)
        {
          /* If sucessful, print it. */
          printf ("Output:\n%s\n", p);
          gsasl_free (p);
        }

      if (rc == GSASL_NEEDS_MORE)
        {
          /* If the client need more data from server, get it here. */
          printf ("Input base64 encoded data from server:\n");
          p = fgets (buf, sizeof (buf) - 1, stdin);
	  if (p == NULL)
	    {
	      perror ("fgets");
	      return;
	    }
          if (buf[strlen (buf) - 1] == '\n')
            buf[strlen (buf) - 1] = '\0';
        }
    }
  while (rc == GSASL_NEEDS_MORE);

  printf ("\n");

  if (rc != GSASL_OK)
    {
      printf ("Authentication error (%d): %s\n", rc, gsasl_strerror (rc));
      return;
    }

  /* The client is done.  Here you would typically check if the server
     let the client in.  If not, you could try again. */

  printf ("If server accepted us, we're done.\n");
}
Exemplo n.º 9
0
static void
server_auth (FILE * fh, Gsasl_session * session)
{
  char *line = NULL;
  size_t n = 0;
  char *p;
  int rc;

  /* The ordering and the type of checks in the following loop has to
     be adapted for each protocol depending on its SASL properties.
     SMTP is a "server-first" SASL protocol.  This implementation do
     not support piggy-backing of the initial client challenge nor
     piggy-backing of the terminating server response.  See RFC 2554
     and RFC 4422 for terminology.  That profile results in the
     following loop structure.  Ask on the help-gsasl list if you are
     uncertain.  */
  do
    {
      rc = gsasl_step64 (session, line, &p);
      if (rc == GSASL_NEEDS_MORE || (rc == GSASL_OK && p && *p))
	{
	  print (fh, "334 %s\n", p);
	  gsasl_free (p);

	  if (gettrimline (&line, &n, fh) < 0)
	    {
	      print (fh, "221 localhost getline failure\n");
	      goto done;
	    }
	}
    }
  while (rc == GSASL_NEEDS_MORE);

  if (rc != GSASL_OK)
    {
      print (fh, "535 gsasl_step64 (%d): %s\n", rc, gsasl_strerror (rc));
      goto done;
    }

  {
    const char *authid = gsasl_property_fast (session, GSASL_AUTHID);
    const char *authzid = gsasl_property_fast (session, GSASL_AUTHZID);
    print (fh, "235 OK [authid: %s authzid: %s]\n",
	   authid ? authid : "N/A", authzid ? authzid : "N/A");
  }

done:
  free (line);
}
Exemplo n.º 10
0
static void
client (Gsasl * ctx)
{
  Gsasl_session *session;
  const char *mech = "SECURID";
  int rc;

  /* Create new authentication session. */
  if ((rc = gsasl_client_start (ctx, mech, &session)) != GSASL_OK)
    {
      printf ("Cannot initialize client (%d): %s\n", rc, gsasl_strerror (rc));
      return;
    }

  /* Do it. */
  client_authenticate (session);

  /* Cleanup. */
  gsasl_finish (session);
}
Exemplo n.º 11
0
int
main (int argc, char *argv[])
{
  Gsasl *ctx = NULL;
  int rc;

  /* Initialize library. */
  if ((rc = gsasl_init (&ctx)) != GSASL_OK)
    {
      printf ("Cannot initialize libgsasl (%d): %s", rc, gsasl_strerror (rc));
      return 1;
    }

  /* Do it. */
  client (ctx);

  /* Cleanup. */
  gsasl_done (ctx);

  return 0;
}
Exemplo n.º 12
0
void
doit (void)
{
  Gsasl_ctx *ctx = NULL;
  Gsasl_session_ctx *server = NULL, *client = NULL;
  char *s1 = NULL, *s2 = NULL;
  int rc, res1, res2;

  rc = gsasl_init (&ctx);
  if (rc != GSASL_OK)
    {
      fail ("gsasl_init() failed (%d):\n%s\n", rc, gsasl_strerror (rc));
      return;
    }

  gsasl_client_callback_service_set (ctx, client_cb_service);
  gsasl_client_callback_authentication_id_set (ctx,
					       client_cb_authentication_id);

  gsasl_server_callback_gssapi_set (ctx, server_cb_gssapi);

  for (i = 0; i < 5; i++)
    {
      rc = gsasl_server_start (ctx, "GSSAPI", &server);
      if (rc != GSASL_OK)
	{
	  fail ("gsasl_server_start() failed (%d):\n%s\n",
		rc, gsasl_strerror (rc));
	  return;
	}
      rc = gsasl_client_start (ctx, "GSSAPI", &client);
      if (rc != GSASL_OK)
	{
	  fail ("gsasl_client_start() failed (%d):\n%s\n",
		rc, gsasl_strerror (rc));
	  return;
	}

      do
	{
	  res1 = gsasl_step64 (server, s1, &s2);
	  if (s1)
	    {
	      free (s1);
	      s1 = NULL;
	    }
	  if (res1 != GSASL_OK && res1 != GSASL_NEEDS_MORE)
	    {
	      fail ("gsasl_step64 (1) failed (%d):\n%s\n", res1,
		    gsasl_strerror (res1));
	      return;
	    }

	  if (debug)
	    printf ("S: %s\n", s2);

	  if (res1 == GSASL_OK && strcmp (s2, "") == 0)
	    break;

	  res2 = gsasl_step64 (client, s2, &s1);
	  free (s2);
	  if (res2 != GSASL_OK && res2 != GSASL_NEEDS_MORE)
	    {
	      fail ("gsasl_step64 (2) failed (%d):\n%s\n", res2,
		    gsasl_strerror (res2));
	      return;
	    }

	  if (debug)
	    printf ("C: %s\n", s1);
	}
      while (res1 != GSASL_OK || res2 != GSASL_OK);

      if (s1)
	{
	  free (s1);
	  s1 = NULL;
	}

      if (debug)
	printf ("\n");

      gsasl_client_finish (client);
      gsasl_server_finish (server);
    }

  gsasl_done (ctx);
}
Exemplo n.º 13
0
void
doit (void)
{
  Gsasl *ctx = NULL;
  Gsasl_session *sctx = NULL;
  char *out = NULL;
  int i, j;
  int res;

  if (!gsasl_check_version (GSASL_VERSION))
    fail ("gsasl_check_version failure");

  success ("Header version %s library version %s\n",
	   GSASL_VERSION, gsasl_check_version (NULL));

  res = gsasl_init (&ctx);
  if (res != GSASL_OK)
    {
      fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res));
      return;
    }

  gsasl_callback_set (ctx, cb);

  res = gsasl_client_mechlist (ctx, &out);
  if (res != GSASL_OK)
    fail ("gsasl_client_mechlist() failed (%d):\n%s\n",
	  res, gsasl_strerror (res));
  success ("client_mechlist: %s\n", out);
  gsasl_free (out);
  out = NULL;

  res = gsasl_server_mechlist (ctx, &out);
  if (res != GSASL_OK)
    fail ("gsasl_server_mechlist() failed (%d):\n%s\n",
	  res, gsasl_strerror (res));
  success ("server_mechlist: %s\n", out);
  gsasl_free (out);
  out = NULL;

  for (i = 0; i < sizeof (sasltv) / sizeof (sasltv[0]); i++)
    {
      gsasl_callback_hook_set (ctx, &i);

      if (debug)
	printf ("Entry %d %s mechanism %s:\n",
		i, sasltv[i].clientp ? "client" : "server", sasltv[i].mech);

      if (sasltv[i].clientp)
	res = gsasl_client_support_p (ctx, sasltv[i].mech);
      else
	res = gsasl_server_support_p (ctx, sasltv[i].mech);
      if (!res)
	continue;

      if (sasltv[i].clientp)
	res = gsasl_client_start (ctx, sasltv[i].mech, &sctx);
      else
	res = gsasl_server_start (ctx, sasltv[i].mech, &sctx);
      if (res != GSASL_OK)
	{
	  fail ("SASL %s start for mechanism %s failed (%d):\n%s\n",
		sasltv[i].clientp ? "client" : "server",
		sasltv[i].mech, res, gsasl_strerror (res));
	  continue;
	}

      for (j = 0; sasltv[i].step[j]; j += 2)
	{
	  gsasl_session_hook_set (sctx, &j);

	  if (debug)
	    printf ("Input : %s\n",
		    sasltv[i].step[j] ? sasltv[i].step[j] : "");

	  res = gsasl_step64 (sctx, sasltv[i].step[j], &out);

	  if (debug)
	    printf ("Output: %s\n", out ? out : "(null)");

	  if (res != GSASL_OK && res != GSASL_NEEDS_MORE)
	    {
	      fail ("gsasl_step64 failed (%d): %s", res,
		    gsasl_strerror (res));
	      break;
	    }

	  if (strlen (out) !=
	      strlen (sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : ""))
	    {
	      printf ("Expected: %s\n", sasltv[i].step[j + 1] ?
		      sasltv[i].step[j + 1] : "");
	      fail
		("SASL entry %d mechanism %s client step %d length error\n",
		 i, sasltv[i].mech, j);
	      j = -1;
	      break;
	    }

	  if (strcmp (out, sasltv[i].step[j + 1] ?
		      sasltv[i].step[j + 1] : "") != 0)
	    {
	      printf ("Expected: %s\n", sasltv[i].step[j + 1] ?
		      sasltv[i].step[j + 1] : "");
	      fail ("SASL entry %d mechanism %s client step %d data error\n",
		    i, sasltv[i].mech, j);
	      j = -1;
	      break;
	    }

	  gsasl_free (out);
	  out = NULL;

	  if (strcmp (sasltv[i].mech, "SECURID") != 0 && res == GSASL_OK)
	    break;
	}

      if (j != (size_t) - 1 && res == GSASL_OK && sasltv[i].step[j + 2])
	fail ("SASL entry %d mechanism %s step %d code ended prematurely\n",
	      i, sasltv[i].mech, j);
      else if (j != (size_t) - 1 && res == GSASL_NEEDS_MORE)
	fail ("SASL entry %d mechanism %s step %d table ended prematurely\n",
	      i, sasltv[i].mech, j);
      else if (j != (size_t) - 1 && res != GSASL_OK)
	fail ("SASL entry %d mechanism %s step %d failed (%d):\n%s\n",
	      i, sasltv[i].mech, j, res, gsasl_strerror (res));
      else
	printf ("PASS: simple %s %s %d\n", sasltv[i].mech,
		sasltv[i].clientp ? "client" : "server", i);

      {
	size_t outlen;

	res = gsasl_encode (sctx, "foo", 3, &out, &outlen);
	if (res != GSASL_OK)
	  fail ("gsasl_encode %d: %s\n", res, gsasl_strerror (res));
	if (outlen != 3 && memcmp (out, "foo", outlen) != 0)
	  fail ("gsasl_encode memcmp: %.*s\n", (int) outlen, out);
	gsasl_free (out);
	out = NULL;

	res = gsasl_decode (sctx, "foo", 3, &out, &outlen);
	if (res != GSASL_OK)
	  fail ("gsasl_decode %d: %s\n", res, gsasl_strerror (res));
	if (outlen != 3 && memcmp (out, "foo", outlen) != 0)
	  fail ("gsasl_decode memcmp: %.*s\n", (int) outlen, out);
	gsasl_free (out);
	out = NULL;
      }

      gsasl_finish (sctx);

      if (debug)
	printf ("\n");
    }

  gsasl_done (ctx);

  /* Sanity check interfaces. */
  gsasl_finish (NULL);
  gsasl_done (NULL);
}
Exemplo n.º 14
0
void
doit (void)
{
  Gsasl *ctx = NULL;
  const char *str;
  const char *p;
  int res;

  res = gsasl_init (&ctx);
  if (res != GSASL_OK)
    {
      fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res));
      return;
    }

  str = "FOO BAR FOO";
  p = gsasl_client_suggest_mechanism (ctx, str);
  if (debug)
    printf ("gsasl_client_suggest_mechanism(%s) = %s\n", str,
	    p ? p : "(null)");
  if (p)
    fail ("FAIL: not null?!\n");

  if (gsasl_client_support_p (ctx, "EXTERNAL"))
    {
      str = "FOO BAR EXTERNAL BAR FOO";
      p = gsasl_client_suggest_mechanism (ctx, str);
      if (debug)
	printf ("gsasl_client_suggest_mechanism(%s) = %s\n", str, p);
      if (!p || strcmp (p, "EXTERNAL") != 0)
	fail ("FAIL: not external?!\n");
    }

  if (gsasl_client_support_p (ctx, "CRAM-MD5"))
    {
      str = "FOO BAR CRAM-MD5 BAR FOO";
      p = gsasl_client_suggest_mechanism (ctx, str);
      if (debug)
	printf ("gsasl_client_suggest_mechanism(%s) = %s\n", str, p);
      if (!p || strcmp (p, "CRAM-MD5") != 0)
	fail ("FAIL: not cram-md5?!\n");
    }

  if (gsasl_client_support_p (ctx, "PLAIN")
      && gsasl_client_support_p (ctx, "CRAM-MD5"))
    {
      str = "FOO PLAIN CRAM-MD5 BAR FOO";
      p = gsasl_client_suggest_mechanism (ctx, str);
      if (debug)
	printf ("gsasl_client_suggest_mechanism(%s) = %s\n", str, p);
      if (!p || strcmp (p, "CRAM-MD5") != 0)
	fail ("FAIL: not cram-md5?!\n");
    }

  if (gsasl_client_support_p (ctx, "PLAIN"))
    {
      str = "FOO PLAIN BAR FOO";
      p = gsasl_client_suggest_mechanism (ctx, str);
      if (debug)
	printf ("gsasl_client_suggest_mechanism(%s) = %s\n", str, p);
      if (!p || strcmp (p, "PLAIN") != 0)
	fail ("FAIL: not plain?!\n");
    }

  if (gsasl_client_support_p (ctx, "PLAIN")
      && gsasl_client_support_p (ctx, "CRAM-MD5")
      && gsasl_client_support_p (ctx, "DIGEST-MD5"))
    {
      str = "FOO PLAIN CRAM-MD5 DIGEST-MD5 FOO";
      p = gsasl_client_suggest_mechanism (ctx, str);
      if (debug)
	printf ("gsasl_client_suggest_mechanism(%s) = %s\n", str, p);
      if (!p || strcmp (p, "CRAM-MD5") != 0)
	fail ("FAIL: not cram-md5?!\n");
    }

  gsasl_done (ctx);
}
Exemplo n.º 15
0
void
doit (void)
{
  Gsasl_ctx *ctx = NULL;
  Gsasl_session_ctx *xctx = NULL;
  char output[MAX_LINE_LENGTH];
  size_t outputlen;
  int i, j;
  int res;

  if (!gsasl_check_version (GSASL_VERSION))
    fail ("gsasl_check_version failure");

  success ("Header version %s library version %s\n",
	   GSASL_VERSION, gsasl_check_version (NULL));

  res = gsasl_init (&ctx);
  if (res != GSASL_OK)
    {
      fail ("gsasl_init() failed (%d):\n%s\n", res, gsasl_strerror (res));
      return;
    }

  gsasl_client_callback_authentication_id_set
    (ctx, client_callback_authentication_id);
  gsasl_client_callback_authorization_id_set
    (ctx, client_callback_authorization_id);
  gsasl_client_callback_password_set (ctx, client_callback_password);
  gsasl_server_callback_validate_set (ctx, server_callback_validate);
  gsasl_server_callback_retrieve_set (ctx, server_callback_retrieve);
  gsasl_client_callback_service_set (ctx, client_callback_service);
  gsasl_client_callback_anonymous_set (ctx, client_callback_anonymous);
  gsasl_server_callback_anonymous_set (ctx, server_callback_anonymous);
  gsasl_server_callback_external_set (ctx, server_callback_external);
  gsasl_client_callback_passcode_set (ctx, client_callback_passcode);
  gsasl_client_callback_pin_set (ctx, client_callback_pin);
  gsasl_server_callback_securid_set (ctx, server_callback_securid);

  outputlen = sizeof (output);
  res = gsasl_client_listmech (ctx, output, &outputlen);
  if (res != GSASL_OK)
    fail ("gsasl_client_listmech() failed (%d):\n%s\n",
	  res, gsasl_strerror (res));

  outputlen = sizeof (output);
  res = gsasl_server_listmech (ctx, output, &outputlen);
  if (res != GSASL_OK)
    fail ("gsasl_server_listmech() failed (%d):\n%s\n",
	  res, gsasl_strerror (res));

  for (i = 0; i < sizeof (sasltv) / sizeof (sasltv[0]); i++)
    {
      gsasl_application_data_set (ctx, &i);

      if (debug)
	printf ("Entry %d %s mechanism %s:\n",
		i, sasltv[i].clientp ? "client" : "server", sasltv[i].mech);

      if (sasltv[i].clientp)
	res = gsasl_client_support_p (ctx, sasltv[i].mech);
      else
	res = gsasl_server_support_p (ctx, sasltv[i].mech);
      if (!res)
	continue;

      if (sasltv[i].clientp)
	res = gsasl_client_start (ctx, sasltv[i].mech, &xctx);
      else
	res = gsasl_server_start (ctx, sasltv[i].mech, &xctx);
      if (res != GSASL_OK)
	{
	  fail ("SASL %s start for mechanism %s failed (%d):\n%s\n",
		sasltv[i].clientp ? "client" : "server",
		sasltv[i].mech, res, gsasl_strerror (res));
	  continue;
	}

      for (j = 0; sasltv[i].step[j]; j += 2)
	{
	  if (sasltv[i].clientp)
	    gsasl_client_application_data_set (xctx, &j);
	  else
	    gsasl_server_application_data_set (xctx, &j);

	  if (debug)
	    printf ("Input : %s\n",
		    sasltv[i].step[j] ? sasltv[i].step[j] : "");

	  output[0] = '\0';
	  outputlen = sizeof (output);
	  if (sasltv[i].clientp)
	    res = gsasl_client_step_base64 (xctx, sasltv[i].step[j],
					    output, outputlen);
	  else
	    res = gsasl_server_step_base64 (xctx, sasltv[i].step[j],
					    output, outputlen);

	  if (debug)
	    printf ("Output: %s\n", output);

	  if (res != GSASL_OK && res != GSASL_NEEDS_MORE)
	    break;

	  if (strlen (output) !=
	      strlen (sasltv[i].step[j + 1] ? sasltv[i].step[j + 1] : ""))
	    {
	      printf ("Expected: %s\n", sasltv[i].step[j + 1] ?
		      sasltv[i].step[j + 1] : "");
	      fail
		("SASL entry %d mechanism %s client step %d length error\n",
		 i, sasltv[i].mech, j);
	      j = -1;
	      break;
	    }

	  if (strcmp (output, sasltv[i].step[j + 1] ?
		      sasltv[i].step[j + 1] : "") != 0)
	    {
	      printf ("Expected: %s\n", sasltv[i].step[j + 1] ?
		      sasltv[i].step[j + 1] : "");
	      fail ("SASL entry %d mechanism %s client step %d data error\n",
		    i, sasltv[i].mech, j);
	      j = -1;
	      break;
	    }

	  if (strcmp (sasltv[i].mech, "SECURID") != 0 && res == GSASL_OK)
	    break;
	}

      if (j != (size_t) - 1 && res == GSASL_OK && sasltv[i].step[j + 2])
	fail ("SASL entry %d mechanism %s step %d code ended prematurely\n",
	      i, sasltv[i].mech, j);
      else if (j != (size_t) - 1 && res == GSASL_NEEDS_MORE)
	fail ("SASL entry %d mechanism %s step %d table ended prematurely\n",
	      i, sasltv[i].mech, j);
      else if (j != (size_t) - 1 && res != GSASL_OK)
	fail ("SASL entry %d mechanism %s step %d failed (%d):\n%s\n",
	      i, sasltv[i].mech, j, res, gsasl_strerror (res));
      else
	printf ("PASS: simple %s %s %d\n", sasltv[i].mech,
		sasltv[i].clientp ? "client" : "server", i);

      if (sasltv[i].clientp)
	gsasl_client_finish (xctx);
      else
	gsasl_server_finish (xctx);

      if (debug)
	printf ("\n");
    }

  gsasl_done (ctx);
}
Exemplo n.º 16
0
int
main (int argc, char *argv[])
{
  Gsasl *ctx = NULL;
  int res;
  char *in;
  char *connect_hostname = NULL;
  char *connect_service = NULL;
#ifdef HAVE_LIBGNUTLS
  gnutls_anon_client_credentials anoncred;
  gnutls_certificate_credentials x509cred;
#endif

  set_program_name (argv[0]);
  setlocale (LC_ALL, "");
  bindtextdomain (PACKAGE, LOCALEDIR);
  textdomain (PACKAGE);

  /* This is necessary for modern MinGW compilers that provide working
     getaddrinfo function, which results in gnulib not detecting that
     it is broken.  The proper fix is for gnulib to wrap the
     getaddrinfo call and initialize Windows sockets in the
     wrapper.  */
  (void) gl_sockets_startup (SOCKETS_1_1);

  if (cmdline_parser (argc, argv, &args_info) != 0)
    return EXIT_FAILURE;

  if (args_info.version_given)
    {
      const char *p = PACKAGE_NAME;
      if (strcmp (gsasl_check_version (NULL), PACKAGE_VERSION) != 0)
	p = PACKAGE_STRING;
      version_etc (stdout, "gsasl", p, gsasl_check_version (NULL),
		   "Simon Josefsson", (char *) NULL);
      return EXIT_SUCCESS;
    }

  if (args_info.help_given)
    usage (EXIT_SUCCESS);

  if (!(args_info.client_flag || args_info.client_given) &&
      !args_info.server_given &&
      !args_info.client_mechanisms_flag && !args_info.server_mechanisms_flag)
    {
      error (0, 0, _("missing argument"));
      usage (EXIT_FAILURE);
    }

  if ((args_info.x509_cert_file_arg && !args_info.x509_key_file_arg) ||
      (!args_info.x509_cert_file_arg && args_info.x509_key_file_arg))
    error (EXIT_FAILURE, 0,
	   _("need both --x509-cert-file and --x509-key-file"));

  if (args_info.starttls_flag && args_info.no_starttls_flag)
    error (EXIT_FAILURE, 0,
	   _("cannot use both --starttls and --no-starttls"));

  if (args_info.smtp_flag && args_info.imap_flag)
    error (EXIT_FAILURE, 0, _("cannot use both --smtp and --imap"));

  if (!args_info.connect_given && args_info.inputs_num == 0 &&
      !args_info.client_given && !args_info.server_given &&
      !args_info.client_mechanisms_flag && !args_info.server_mechanisms_flag)
    {
      cmdline_parser_print_help ();
      emit_bug_reporting_address ();
      return EXIT_SUCCESS;
    }

  if (args_info.connect_given)
    {
      if (strrchr (args_info.connect_arg, ':'))
	{
	  connect_hostname = xstrdup (args_info.connect_arg);
	  *strrchr (connect_hostname, ':') = '\0';
	  connect_service =
	    xstrdup (strrchr (args_info.connect_arg, ':') + 1);
	}
      else
	{
	  connect_hostname = xstrdup (args_info.connect_arg);
	  if (args_info.smtp_flag)
	    connect_service = xstrdup ("smtp");
	  else
	    connect_service = xstrdup ("imap");
	}
    }
  else if (args_info.inputs_num > 0)
    {
      connect_hostname = args_info.inputs[0];
      if (args_info.inputs_num > 1)
	connect_service = args_info.inputs[1];
      else if (args_info.smtp_flag)
	connect_service = xstrdup ("smtp");
      else
	connect_service = xstrdup ("imap");
    }

  if (connect_service && !args_info.smtp_flag && !args_info.imap_flag)
    {
      if (strcmp (connect_service, "25") == 0 ||
	  strcmp (connect_service, "smtp") == 0)
	args_info.smtp_flag = 1;
      else
	args_info.imap_flag = 1;
    }

  if (args_info.imap_flag && !args_info.service_given)
    args_info.service_arg = xstrdup ("imap");

  if (args_info.smtp_flag && !args_info.service_given)
    args_info.service_arg = xstrdup ("smtp");

  if (args_info.imap_flag || args_info.smtp_flag)
    args_info.no_client_first_flag = 1;

  if (connect_hostname && !args_info.hostname_arg)
    args_info.hostname_arg = xstrdup (connect_hostname);

  if (!isatty (STDOUT_FILENO))
    setvbuf (stdout, NULL, _IOLBF, BUFSIZ);

  res = gsasl_init (&ctx);
  if (res != GSASL_OK)
    error (EXIT_FAILURE, 0, _("initialization failure: %s"),
	   gsasl_strerror (res));

  gsasl_callback_set (ctx, callback);

  if (args_info.client_mechanisms_flag || args_info.server_mechanisms_flag)
    {
      char *mechs;

      if (args_info.client_mechanisms_flag)
	res = gsasl_client_mechlist (ctx, &mechs);
      else
	res = gsasl_server_mechlist (ctx, &mechs);

      if (res != GSASL_OK)
	error (EXIT_FAILURE, 0, _("error listing mechanisms: %s"),
	       gsasl_strerror (res));

      if (!args_info.quiet_given)
	{
	  if (args_info.client_mechanisms_flag)
	    fprintf (stderr,
		     _("This client supports the following mechanisms:\n"));
	  else
	    fprintf (stderr,
		     _("This server supports the following mechanisms:\n"));
	}

      fprintf (stdout, "%s\n", mechs);

      free (mechs);

      return EXIT_SUCCESS;
    }

  if (args_info.connect_given || args_info.inputs_num > 0)
    {
      struct addrinfo hints;
      struct addrinfo *ai0, *ai;

      memset (&hints, 0, sizeof (hints));
      hints.ai_flags = AI_CANONNAME;
      hints.ai_socktype = SOCK_STREAM;
      res = getaddrinfo (connect_hostname, connect_service, &hints, &ai0);
      if (res != 0)
	error (EXIT_FAILURE, 0, "%s: %s", connect_hostname,
	       gai_strerror (res));

      for (ai = ai0; ai; ai = ai->ai_next)
	{
	  fprintf (stderr, "Trying %s...\n", quote (ai->ai_canonname ?
						    ai->ai_canonname :
						    connect_hostname));

	  sockfd = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
	  if (sockfd < 0)
	    {
	      error (0, errno, "socket");
	      continue;
	    }

	  if (connect (sockfd, ai->ai_addr, ai->ai_addrlen) < 0)
	    {
	      int save_errno = errno;
	      close (sockfd);
	      sockfd = -1;
	      error (0, save_errno, "connect");
	      continue;
	    }
	  break;
	}

      if (sockfd < 0)
	error (EXIT_FAILURE, errno, "socket");

      freeaddrinfo (ai);
    }

  if (!greeting ())
    return 1;

#ifdef HAVE_LIBGNUTLS
  if (sockfd && !args_info.no_starttls_flag &&
      (args_info.starttls_flag || has_starttls ()))
    {
      res = gnutls_global_init ();
      if (res < 0)
	error (EXIT_FAILURE, 0, _("GnuTLS global initialization failed: %s"),
	       gnutls_strerror (res));

      res = gnutls_init (&session, GNUTLS_CLIENT);
      if (res < 0)
	error (EXIT_FAILURE, 0, _("GnuTLS initialization failed: %s"),
	       gnutls_strerror (res));

      res = gnutls_set_default_priority (session);
      if (res < 0)
	error (EXIT_FAILURE, 0, _("setting GnuTLS defaults failed: %s"),
	       gnutls_strerror (res));

      res = gnutls_anon_allocate_client_credentials (&anoncred);
      if (res < 0)
	error (EXIT_FAILURE, 0,
	       _("allocating anonymous GnuTLS credential: %s"),
	       gnutls_strerror (res));

      res = gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
      if (res < 0)
	error (EXIT_FAILURE, 0, _("setting anonymous GnuTLS credential: %s"),
	       gnutls_strerror (res));

      res = gnutls_certificate_allocate_credentials (&x509cred);
      if (res < 0)
	error (EXIT_FAILURE, 0, _("allocating X.509 GnuTLS credential: %s"),
	       gnutls_strerror (res));

      if (args_info.x509_cert_file_arg && args_info.x509_key_file_arg)
	res = gnutls_certificate_set_x509_key_file
	  (x509cred, args_info.x509_cert_file_arg,
	   args_info.x509_key_file_arg, GNUTLS_X509_FMT_PEM);
      if (res != GNUTLS_E_SUCCESS)
	error (EXIT_FAILURE, 0, _("loading X.509 GnuTLS credential: %s"),
	       gnutls_strerror (res));

      if (args_info.x509_ca_file_arg)
	{
	  res = gnutls_certificate_set_x509_trust_file
	    (x509cred, args_info.x509_ca_file_arg, GNUTLS_X509_FMT_PEM);
	  if (res < 0)
	    error (EXIT_FAILURE, 0, _("no X.509 CAs found: %s"),
		   gnutls_strerror (res));
	  if (res == 0)
	    error (EXIT_FAILURE, 0, _("no X.509 CAs found"));
	}

      res = gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE,
				    x509cred);
      if (res < 0)
	error (EXIT_FAILURE, 0, _("setting X.509 GnuTLS credential: %s"),
	       gnutls_strerror (res));

      if (args_info.priority_arg)
	{
	  const char *err_pos;

	  res = gnutls_priority_set_direct (session, args_info.priority_arg,
					    &err_pos);
	  if (res < 0)
	    error (EXIT_FAILURE, 0,
		   _("setting GnuTLS cipher priority (%s): %s\n"),
		   gnutls_strerror (res), err_pos);
	}

      gnutls_transport_set_ptr (session, (gnutls_transport_ptr)
				(unsigned long) sockfd);

      if (!starttls ())
	return 1;

      res = gnutls_handshake (session);
      if (res < 0)
	error (EXIT_FAILURE, 0, _("GnuTLS handshake failed: %s"),
	       gnutls_strerror (res));

      if (args_info.x509_ca_file_arg)
	{
	  unsigned int status;

	  res = gnutls_certificate_verify_peers2 (session, &status);
	  if (res < 0)
	    error (EXIT_FAILURE, 0, _("verifying peer certificate: %s"),
		   gnutls_strerror (res));

	  if (status & GNUTLS_CERT_INVALID)
	    error (EXIT_FAILURE, 0, _("server certificate is not trusted"));

	  if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
	    error (EXIT_FAILURE, 0,
		   _("server certificate hasn't got a known issuer"));

	  if (status & GNUTLS_CERT_REVOKED)
	    error (EXIT_FAILURE, 0, _("server certificate has been revoked"));

	  if (status != 0)
	    error (EXIT_FAILURE, 0,
		   _("could not verify server certificate (rc=%d)"), status);
	}

#if HAVE_GNUTLS_SESSION_CHANNEL_BINDING
      if (!args_info.no_cb_flag)
	{
	  gnutls_datum cb;

	  res = gnutls_session_channel_binding (session,
						GNUTLS_CB_TLS_UNIQUE, &cb);
	  if (res != GNUTLS_E_SUCCESS)
	    error (EXIT_FAILURE, 0, _("getting channel binding failed: %s"),
		   gnutls_strerror (res));

	  res = gsasl_base64_to ((char *) cb.data, cb.size,
				 &b64cbtlsunique, NULL);
	  if (res != GSASL_OK)
	    error (EXIT_FAILURE, 0, "%s", gsasl_strerror (res));
	}
#endif

      using_tls = true;
    }
#endif

  if (args_info.client_flag || args_info.client_given
      || args_info.server_given)
    {
      char *out;
      char *b64output;
      size_t output_len;
      size_t b64output_len;
      const char *mech;
      Gsasl_session *xctx = NULL;

      if (!select_mechanism (&in))
	return 1;

      mech = gsasl_client_suggest_mechanism (ctx, in);
      if (mech == NULL)
	{
	  fprintf (stderr, _("Cannot find mechanism...\n"));
	  return 0;
	}

      if (args_info.mechanism_arg)
	mech = args_info.mechanism_arg;

      if (!authenticate (mech))
	return 1;

      /* Authenticate using mechanism */

      if (args_info.server_flag)
	res = gsasl_server_start (ctx, mech, &xctx);
      else
	res = gsasl_client_start (ctx, mech, &xctx);
      if (res != GSASL_OK)
	error (EXIT_FAILURE, 0, _("mechanism unavailable: %s"),
	       gsasl_strerror (res));

      in = NULL;
      out = NULL;

      if (!args_info.server_flag && args_info.no_client_first_flag)
	{
	  res = GSASL_NEEDS_MORE;
	  goto no_client_first;
	}

      do
	{
	  int res2;

	  res = gsasl_step64 (xctx, in, &out);
	  if (res != GSASL_NEEDS_MORE && res != GSASL_OK)
	    break;

	  if (!step_send (out))
	    return 1;

	no_client_first:
	  if (!args_info.quiet_given &&
	      !args_info.imap_flag && !args_info.smtp_flag)
	    {
	      if (args_info.server_flag)
		fprintf (stderr, _("Enter base64 authentication data "
				   "from client (press RET if none):\n"));
	      else
		fprintf (stderr, _("Enter base64 authentication data "
				   "from server (press RET if none):\n"));
	    }

	  /* Return 1 on token, 2 on protocol success, 3 on protocol fail, 0 on
	     errors. */
	  res2 = step_recv (&in);
	  if (!res2)
	    return 1;
	  if (res2 == 3)
	    error (EXIT_FAILURE, 0, _("server error"));
	  if (res2 == 2)
	    break;
	}
      while (args_info.imap_flag || args_info.smtp_flag
	     || res == GSASL_NEEDS_MORE);

      if (res != GSASL_OK)
	error (EXIT_FAILURE, 0, _("mechanism error: %s"),
	       gsasl_strerror (res));

      if (!args_info.quiet_given)
	{
	  if (args_info.server_flag)
	    fprintf (stderr, _("Server authentication "
			       "finished (client trusted)...\n"));
	  else
	    fprintf (stderr, _("Client authentication "
			       "finished (server trusted)...\n"));
	  fflush (stderr);
	}

      /* Transfer application payload */
      if (args_info.application_data_flag)
	{
	  struct pollfd pfd[2];
	  char *sockbuf = NULL;
	  /* we read chunks of 1000 bytes at a time */
	  size_t sockpos = 0, sockalloc = 0, sockalloc1 = 1000;

	  /* Setup pollfd structs... */
	  pfd[0].fd = STDIN_FILENO;
	  pfd[0].events = POLLIN;
	  if (sockfd)
	    {
	      pfd[1].fd = sockfd;
	      pfd[1].events = POLLIN;
	    }

	  if (!args_info.quiet_given)
	    {
	      fprintf (stderr,
		       _("Enter application data (EOF to finish):\n"));
	      fflush (stderr);
	    }

	  while (1)
	    {
	      int rc;

	      pfd[0].revents = 0;
	      pfd[1].revents = 0;

	      rc = poll (pfd, sockfd ? 2 : 1, -1);
	      if (rc < 0 && errno == EINTR)
		continue;

	      /* Always check for errors */
	      if (rc < 0)
		error (EXIT_FAILURE, errno, "poll");

	      /* We got data to read from stdin.. */
	      if ((pfd[0].revents & (POLLIN | POLLERR)) == POLLIN)
		{
		  char *line = NULL;
		  size_t n;
		  ssize_t len;

		  len = getline (&line, &n, stdin);
		  if (len <= 0)
		    break;

		  if (args_info.imap_flag || args_info.smtp_flag)
		    {
		      if (len < 2 || strcmp (&line[len - 2], "\r\n") != 0)
			{
			  line = xrealloc (line, len + 2);
			  line[len - 1] = '\r';
			  line[len] = '\n';
			  line[len + 1] = '\0';
			  len++;
			}
		    }
		  else
		    {
		      len--;
		      line[len] = '\0';
		    }

		  res = gsasl_encode (xctx, line, len, &out, &output_len);
		  if (res != GSASL_OK)
		    break;

		  if (sockfd)
		    {
#ifdef HAVE_LIBGNUTLS
		      if (using_tls)
			len = gnutls_record_send (session, out, output_len);
		      else
#endif
			len = write (sockfd, out, output_len);
		      if (len != output_len)
			error (EXIT_FAILURE, errno, "write");
		    }
		  else if (!(strlen (line) == output_len &&
			     memcmp (line, out, output_len) == 0))
		    {
		      res = gsasl_base64_to (out, output_len,
					     &b64output, &b64output_len);
		      if (res != GSASL_OK)
			break;

		      if (!args_info.quiet_given)
			fprintf (stderr, _("Base64 encoded application "
					   "data to send:\n"));
		      fprintf (stdout, "%s\n", b64output);

		      free (b64output);
		    }

		  free (line);
		  free (out);
		}
	      /* If there was an error, quit.  */
	      else if (pfd[0].revents & (POLLERR | POLLHUP))
		{
		  error (0, 0, "poll stdin");
		  break;
		}

	      /* We got data to read from the socket.. */
	      if (sockfd && (pfd[1].revents & (POLLIN | POLLERR)) == POLLIN)
		{
		  ssize_t len;

		  if (sockalloc == sockpos)
		    sockbuf = x2realloc (sockbuf, &sockalloc1);
		  sockalloc = sockalloc1;

#ifdef HAVE_LIBGNUTLS
		  if (using_tls)
		    len = gnutls_record_recv (session, &sockbuf[sockpos],
					      sockalloc - sockpos);
		  else
#endif
		    len = recv (sockfd, &sockbuf[sockpos],
				sockalloc - sockpos, 0);
		  if (len <= 0)
		    break;

		  sockpos += len;

		  res = gsasl_decode (xctx, sockbuf, sockpos,
				      &out, &output_len);
		  if (res == GSASL_NEEDS_MORE)
		    {
#define MAX_INPUT_SIZE	0x100000
		      if (sockpos > MAX_INPUT_SIZE)
			error (EXIT_FAILURE, 0,
			       _("SASL record too large: %zu\n"), sockpos);
		      continue;
		    }
		  if (res != GSASL_OK)
		    break;

		  free (sockbuf);
		  sockbuf = NULL;
		  sockpos = 0;
		  sockalloc = 0;
		  sockalloc1 = 1000;

		  printf ("%.*s", (int) output_len, out);
		  free (out);
		}
	      /* If there was an error, quit.  */
	      else if (pfd[1].revents & (POLLERR | POLLHUP))
		{
		  error (0, 0, "poll socket");
		  break;
		}
	    }

	  if (res != GSASL_OK)
	    error (EXIT_FAILURE, 0, _("encoding error: %s"),
		   gsasl_strerror (res));
	}

      if (!args_info.quiet_given)
	fprintf (stderr, _("Session finished...\n"));

      if (!logout ())
	return 1;

      gsasl_finish (xctx);
    }

  if (sockfd)
    {
#ifdef HAVE_LIBGNUTLS
      if (using_tls)
	{
	  res = gnutls_bye (session, GNUTLS_SHUT_RDWR);
	  if (res < 0)
	    error (EXIT_FAILURE, 0,
		   _("terminating GnuTLS session failed: %s"),
		   gnutls_strerror (res));

	}
#endif
      shutdown (sockfd, SHUT_RDWR);
      close (sockfd);
    }

  gsasl_done (ctx);

#ifdef HAVE_LIBGNUTLS
  if (using_tls)
    {
      gnutls_deinit (session);
      gnutls_anon_free_client_credentials (anoncred);
      gnutls_certificate_free_credentials (x509cred);
      gnutls_global_deinit ();
    }
#endif

  return 0;
}
Exemplo n.º 17
0
static int
sasl_auth(dico_stream_t str, char *mechanism, char *initresp,
	  Gsasl_session **psess)
{
    int rc;
    Gsasl_session *sess_ctx;
    char *input;
    char *output;
    char *inbuf;
    size_t insize;
    struct sasl_data sdata = { NULL, 0 };

    if (disabled_mechanism_p(mechanism)) 
	return RC_NOMECH;
    rc = gsasl_server_start (ctx, mechanism, &sess_ctx);
    if (rc != GSASL_OK) {
	dico_log(L_ERR, 0, _("SASL gsasl_server_start: %s"),
		 gsasl_strerror(rc));
	return rc == GSASL_UNKNOWN_MECHANISM ? RC_NOMECH : RC_FAIL;
    }

    gsasl_callback_hook_set(ctx, &sdata);
    output = NULL;
    if (initresp) {
	inbuf = xstrdup(initresp);
	insize = strlen(initresp) + 1;
    } else {
	inbuf = NULL;
	insize = 0;
    }
    input = inbuf;
    while ((rc = gsasl_step64(sess_ctx, input, &output)) == GSASL_NEEDS_MORE) {
	send_challenge(str, output);
	
	free(output);
	output = NULL;
	if (get_sasl_response(str, &input, &inbuf, &insize)) 
	    return RC_FAIL;
    }

    if (rc != GSASL_OK) {
	dico_log(L_ERR, 0, _("GSASL error: %s"), gsasl_strerror(rc));
	free(output);
	free(inbuf);
	gsasl_finish(sess_ctx);
	return RC_FAIL;
    }

    /* Some SASL mechanisms output data when GSASL_OK is returned */
    if (output[0]) 
	send_challenge(str, output);

    free(output);
    free(inbuf);
    
    if (sdata.username == NULL) {
	dico_log(L_ERR, 0, _("GSASL %s: cannot get username"), mechanism);
	gsasl_finish(sess_ctx);
	return RC_FAIL;
    }

    user_name = xstrdup(sdata.username);
    if (sdata.anon) {
	if (sasl_anon_groups) {
	    user_groups = xdico_list_create();
	    dico_list_iterate (sasl_anon_groups, _append_item, user_groups);
	}
    } else
	dico_udb_get_groups(user_db, sdata.username, &user_groups);
    check_db_visibility();

    *psess = sess_ctx;
    return RC_SUCCESS;
}
Exemplo n.º 18
0
static void
client_xmpp (Gsasl_session * session)
{
  char buf[BUFSIZ] = "";
  char *p;
  int rc;

  /* This loop mimics a protocol where the client send data first,
     which is something that XMPP supports.  For simplicity, it
     requires that server send the XML blob on one line and XML parser
     is not complete.  */

  /* Generate client output. */
  rc = gsasl_step64 (session, buf, &p);
  if (rc != GSASL_NEEDS_MORE)
    {
      printf ("SAML20 step error (%d): %s\n", rc, gsasl_strerror (rc));
      return;
    }

  printf ("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' "
	  "mechanism='SAML20'>%s</auth>\n", p);

  do
    {
      char *b64;

      p = fgets (buf, sizeof (buf) - 1, stdin);
      if (p == NULL)
	{
	  perror ("fgets");
	  return;
	}

      if (buf[strlen (buf) - 1] == '\n')
        buf[strlen (buf) - 1] = '\0';

      b64 = xmltob64 (buf);

      printf ("parsed: '%s'\n", b64);

      rc = gsasl_step64 (session, b64, &p);
      if (rc != GSASL_NEEDS_MORE && rc != GSASL_OK)
	{
	  printf ("SAML20 step error (%d): %s\n", rc, gsasl_strerror (rc));
	  return;
	}

      printf ("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>"
	      "%s</response>\n", p);

      gsasl_free (p);
    }
  while (rc == GSASL_NEEDS_MORE);

  if (rc != GSASL_OK)
    {
      printf ("Authentication error (%d): %s\n", rc, gsasl_strerror (rc));
      return;
    }

  /* The client is done.  Here you would typically check if the server
     let the client in.  If not, you could try again. */

  printf ("If server accepted us, we're done.\n");
}
Exemplo n.º 19
0
void
doit (void)
{
  Gsasl *ctx = NULL;
  Gsasl_session *server = NULL, *client = NULL;
  char *s1 = NULL, *s2 = NULL;
  int rc, res1, res2;

  if (getenv ("GNUGSS") && strcmp (getenv ("GNUGSS"), "no") == 0)
    {
      fail ("Not using GNU GSS, skipping self-test.\n");
      exit (77);
    }

  rc = gsasl_init (&ctx);
  if (rc != GSASL_OK)
    {
      fail ("gsasl_init() failed (%d):\n%s\n", rc, gsasl_strerror (rc));
      return;
    }

  if (!gsasl_client_support_p (ctx, "GS2-KRB5")
      || !gsasl_server_support_p (ctx, "GS2-KRB5"))
    {
      gsasl_done (ctx);
      fail ("No support for GS2-KRB5.\n");
      exit (77);
    }

  gsasl_callback_set (ctx, callback);

  for (i = 0; i < 5; i++)
    {
      bool client_first = (i % 2) == 0;

      rc = gsasl_server_start (ctx, "GS2-KRB5", &server);
      if (rc != GSASL_OK)
	{
	  fail ("gsasl_server_start() failed (%d):\n%s\n",
		rc, gsasl_strerror (rc));
	  return;
	}
      rc = gsasl_client_start (ctx, "GS2-KRB5", &client);
      if (rc != GSASL_OK)
	{
	  fail ("gsasl_client_start() failed (%d):\n%s\n",
		rc, gsasl_strerror (rc));
	  return;
	}

      if (client_first)
	{
	  rc = gsasl_step64 (client, NULL, &s1);
	  if (rc != GSASL_OK && rc != GSASL_NEEDS_MORE)
	    {
	      fail ("gsasl_step64 failed (%d):\n%s\n", rc,
		    gsasl_strerror (rc));
	      return;
	    }

	  if (debug)
	    printf ("C: %s [%c]\n", s1, ret_char (rc));
	}

      do
	{
	  res1 = gsasl_step64 (server, s1, &s2);
	  if (s1 == NULL && res1 == GSASL_OK)
	    fail ("gsasl_step64 direct success?\n");
	  if (s1)
	    {
	      gsasl_free (s1);
	      s1 = NULL;
	    }
	  if (res1 != GSASL_OK && res1 != GSASL_NEEDS_MORE)
	    {
	      fail ("gsasl_step64 (1) failed (%d):\n%s\n", res1,
		    gsasl_strerror (res1));
	      return;
	    }

	  if (debug)
	    printf ("S: %s [%c]\n", s2, ret_char (res1));

	  res2 = gsasl_step64 (client, s2, &s1);
	  gsasl_free (s2);
	  if (res2 != GSASL_OK && res2 != GSASL_NEEDS_MORE)
	    {
	      fail ("gsasl_step64 (2) failed (%d):\n%s\n", res2,
		    gsasl_strerror (res2));
	      return;
	    }

	  if (debug)
	    printf ("C: %s [%c]\n", s1, ret_char (res2));
	}
      while (res1 != GSASL_OK || res2 != GSASL_OK);

      if (s1)
	{
	  gsasl_free (s1);
	  s1 = NULL;
	}

      if (debug)
	printf ("\n");

      gsasl_finish (client);
      gsasl_finish (server);
    }

  gsasl_done (ctx);
}
Exemplo n.º 20
0
static void sasl_authenticate( SV *client, mongo_link *link ) { 
  Gsasl *ctx = NULL;
  Gsasl_session *session;
  SV *username, *mechanism, *conv_id;
  HV *result;       /* response document from mongod */
  char *p, *buf;    /* I/O buffers for gsasl */
  int rc;
  char out_buf[8192];

  mechanism = perl_mongo_call_method( client, "sasl_mechanism", 0, 0 );
  if ( !SvOK( mechanism ) ) { 
    croak( "MongoDB: Could not retrieve SASL mechanism from client object\n" );
  }

  if ( strncmp( "PLAIN", SvPV_nolen( mechanism ), 5 ) == 0 ) { 
    /* SASL PLAIN does not require a libgsasl conversation loop, so we can handle it elsewhere */
    return perl_mongo_call_method( client, "_sasl_plain_authenticate", 0, 0 );
  }

  if ( ( rc = gsasl_init( &ctx ) ) != GSASL_OK ) { 
    croak( "MongoDB: Cannot initialize libgsasl (%d): %s\n", rc, gsasl_strerror(rc) );  
  }

  if ( ( rc = gsasl_client_start( ctx, SvPV_nolen( mechanism ), &session ) ) != GSASL_OK ) { 
    croak( "MongoDB: Cannot initialize SASL client (%d): %s\n", rc, gsasl_strerror(rc) );
  }

  username = perl_mongo_call_method( client, "username", 0, 0 );
  if ( !SvOK( username ) ) { 
    croak( "MongoDB: Cannot start SASL session without username. Specify username in constructor\n" );
  }
 
  gsasl_property_set( session, GSASL_SERVICE,  "mongodb" );
  gsasl_property_set( session, GSASL_HOSTNAME, link->master->host );
  gsasl_property_set( session, GSASL_AUTHID,   SvPV_nolen( username ) ); 

  rc = gsasl_step64( session, "", &p );
  if ( ( rc != GSASL_OK ) && ( rc != GSASL_NEEDS_MORE ) ) { 
    croak( "MongoDB: No data from GSSAPI. Did you run kinit?\n" );
  }

  if ( ! strncpy( out_buf, p, 8192 ) ) {
    croak( "MongoDB: Unable to copy SASL output buffer\n" );
  }
  gsasl_free( p );

  result = (HV *)SvRV( perl_mongo_call_method( client, "_sasl_start", 0, 2, newSVpv( out_buf, 0 ), mechanism ) );

#if 0  
  fprintf( stderr, "result conv id = [%s]\n", SvPV_nolen( *hv_fetch( result, "conversationId", 14, FALSE ) ) );
  fprintf( stderr, "result payload = [%s]\n", SvPV_nolen( *hv_fetch( result, "payload",         7, FALSE ) ) );
#endif

  buf = SvPV_nolen( *hv_fetch( result, "payload", 7, FALSE ) );
  conv_id = *hv_fetch( result, "conversationId", 14, FALSE ); 
 
  do { 
    rc = gsasl_step64( session, buf, &p );
    if ( ( rc != GSASL_OK ) && ( rc != GSASL_NEEDS_MORE ) ) {
      croak( "MongoDB: SASL step error (%d): %s\n", rc, gsasl_strerror(rc) );
    }

    if ( ! strncpy( out_buf, p, 8192 ) ) { 
      croak( "MongoDB: Unable to copy SASL output buffer\n" );
    }
    gsasl_free( p );

    result = (HV *)SvRV( perl_mongo_call_method( client, "_sasl_continue", 0, 2, newSVpv( out_buf, 0 ), conv_id ) );
#if 0 
    fprintf( stderr, "result conv id = [%s]\n", SvPV_nolen( *hv_fetch( result, "conversationId", 14, FALSE ) ) );
    fprintf( stderr, "result payload = [%s]\n", SvPV_nolen( *hv_fetch( result, "payload",         7, FALSE ) ) );
#endif

    buf = SvPV_nolen( *hv_fetch( result, "payload", 7, FALSE ) );

  } while( rc == GSASL_NEEDS_MORE );

  if ( rc != GSASL_OK ) { 
    croak( "MongoDB: SASL Authentication error (%d): %s\n", rc, gsasl_strerror(rc) );
  }

  gsasl_finish( session );
  gsasl_done( ctx );
}
Exemplo n.º 21
0
int
main (int argc, char *argv[])
{
  const char *service = argc > 1 ? argv[1] : "2000";
  volatile int run = 1;
  struct addrinfo hints, *addrs;
  int sockfd;
  int rc;
  int yes = 1;
  Gsasl *ctx;
  struct cfg cfg;

  setvbuf (stdout, NULL, _IONBF, 0);

  if (argc != 7)
    {
      printf ("Usage: %s PORT CFG-PATH STATE-PATH SP-METADATA "
	      "SP-KEY SP-CERT\n", argv[0]);
      exit (EXIT_FAILURE);
    }
  cfg.cfg_path = argv[2];
  cfg.state_path = argv[3];
  cfg.sp_metadata = argv[4];
  cfg.sp_key = argv[5];
  cfg.sp_cert = argv[6];

  rc = gsasl_init (&ctx);
  if (rc < 0)
    {
      printf ("gsasl_init (%d): %s\n", rc, gsasl_strerror (rc));
      exit (EXIT_FAILURE);
    }

  printf ("%s [gsasl header %s library %s]\n",
	  argv[0], GSASL_VERSION, gsasl_check_version (NULL));

  gsasl_callback_set (ctx, callback);
  gsasl_callback_hook_set (ctx, &cfg);

  memset (&hints, 0, sizeof (hints));
  hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
  hints.ai_socktype = SOCK_STREAM;

  rc = getaddrinfo (NULL, service, &hints, &addrs);
  if (rc < 0)
    {
      printf ("getaddrinfo: %s\n", gai_strerror (rc));
      exit (EXIT_FAILURE);
    }

  sockfd = socket (addrs->ai_family, addrs->ai_socktype, addrs->ai_protocol);
  if (sockfd < 0)
    {
      perror ("socket");
      exit (EXIT_FAILURE);
    }

  if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof (yes)) < 0)
    {
      perror ("setsockopt");
      exit (EXIT_FAILURE);
    }

  rc = bind (sockfd, addrs->ai_addr, addrs->ai_addrlen);
  if (rc < 0)
    {
      perror ("bind");
      exit (EXIT_FAILURE);
    }

  freeaddrinfo (addrs);

  rc = listen (sockfd, SOMAXCONN);
  if (rc < 0)
    {
      perror ("listen");
      exit (EXIT_FAILURE);
    }

  signal (SIGPIPE, SIG_IGN);

  while (run)
    {
      struct sockaddr from;
      socklen_t fromlen = sizeof (from);
      char host[NI_MAXHOST];
      int fd;
      FILE *fh;

      fd = accept (sockfd, &from, &fromlen);
      if (fd < 0)
	{
	  perror ("accept");
	  continue;
	}

      rc = getnameinfo (&from, fromlen, host, sizeof (host),
			NULL, 0, NI_NUMERICHOST);
      if (rc == 0)
	printf ("connection from %s\n", host);
      else
	printf ("getnameinfo: %s\n", gai_strerror (rc));

      fh = fdopen (fd, "w+");
      if (!fh)
	{
	  perror ("fdopen");
	  close (fd);
	  continue;
	}

      smtp (fh, ctx);

      fclose (fh);
    }

  close (sockfd);
  gsasl_done (ctx);

  return 0;
}