Beispiel #1
0
static int
callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop)
{
  int rc = GSASL_NO_CALLBACK;

  switch (prop)
    {
    case GSASL_AUTHZID:
      if (*AUTHZID[i])
	{
	  gsasl_property_set (sctx, GSASL_AUTHZID, AUTHZID[i]);
	  rc = GSASL_OK;
	}
      break;

    case GSASL_SERVICE:
      gsasl_property_set (sctx, prop, SERVICE);
      rc = GSASL_OK;
      break;

    case GSASL_HOSTNAME:
      gsasl_property_set (sctx, prop, HOST);
      rc = GSASL_OK;
      break;

    case GSASL_VALIDATE_GSSAPI:
      {
	const char *client_name =
	  gsasl_property_fast (sctx, GSASL_GSSAPI_DISPLAY_NAME);
	const char *authzid = gsasl_property_fast (sctx, GSASL_AUTHZID);

	if (client_name)
	  printf ("GSSAPI user: %s\n", client_name);
	else
	  fail ("no client name\n");
	if (authzid)
	  printf ("Authorization ID: %s\n", authzid);

	if (client_name && strcmp (client_name, GSSAPI_USER) == 0 &&
	    ((authzid == NULL && *AUTHZID[i] == '\0')
	     || strcmp (authzid, AUTHZID[i]) == 0))
	  rc = GSASL_OK;
	else
	  rc = GSASL_AUTHENTICATION_ERROR;
      }
      break;

    default:
      fail ("Unknown callback property %d\n", prop);
      break;
    }

  return rc;
}
Beispiel #2
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);
}
Beispiel #3
0
/**
 * gsasl_property_get:
 * @sctx: session handle.
 * @prop: enumerated value of Gsasl_property type, indicating the
 *        type of data in @data.
 *
 * Retrieve the data stored in the session handle for given property
 * @prop, possibly invoking the application callback to get the value.
 *
 * The pointer is to live data, and must not be deallocated or
 * modified in any way.
 *
 * This function will invoke the application callback, using
 * gsasl_callback(), when a property value is not known.
 *
 * If no value is known, and no callback is specified or if the
 * callback fail to return data, and if any obsolete callback
 * functions has been set by the application, this function will try
 * to call these obsolete callbacks, and store the returned data as
 * the corresponding property.  This behaviour of this function will
 * be removed when the obsolete callback interfaces are removed.
 *
 * Return value: Return data for property, or NULL if no value known.
 *
 * Since: 0.2.0
 **/
const char *
gsasl_property_get (Gsasl_session * sctx, Gsasl_property prop)
{
  const char *p = gsasl_property_fast (sctx, prop);

  if (!p)
    {
      gsasl_callback (NULL, sctx, prop);
      p = gsasl_property_fast (sctx, prop);
    }

#ifndef GSASL_NO_OBSOLETE
  if (!p)
    p = _gsasl_obsolete_property_map (sctx, prop);
#endif

  return p;
}
Beispiel #4
0
/** move the stream to the auth state */
void _sx_sasl_open(sx_t s, Gsasl_session *sd) {
    char *method, *authzid;
    const char *realm = NULL;
    struct sx_sasl_creds_st creds = {NULL, NULL, NULL, NULL};
    _sx_sasl_t ctx = gsasl_session_hook_get(sd);
    const char *mechname = gsasl_mechanism_name (sd);

    /* get the method */
    method = (char *) malloc(sizeof(char) * (strlen(mechname) + 6));
    sprintf(method, "SASL/%s", mechname);

    /* and the authorization identifier */
    creds.authzid = gsasl_property_fast(sd, GSASL_AUTHZID);
    creds.authnid = gsasl_property_fast(sd, GSASL_AUTHID);
    creds.realm   = gsasl_property_fast(sd, GSASL_REALM);

    if(0 && ctx && ctx->cb) { /* not supported yet */
        if((ctx->cb)(sx_sasl_cb_CHECK_AUTHZID, &creds, NULL, s, ctx->cbarg)!=sx_sasl_ret_OK) {
            _sx_debug(ZONE, "stream authzid: %s verification failed, not advancing to auth state", creds.authzid);
            free(method);
            return;
        }
    } else if (NULL != gsasl_property_fast(sd, GSASL_GSSAPI_DISPLAY_NAME)) {
        creds.authzid = strdup(gsasl_property_fast(sd, GSASL_GSSAPI_DISPLAY_NAME));
        authzid = NULL;
    } else {
        /* override unchecked arbitrary authzid */
        if(creds.realm && creds.realm[0] != '\0') {
            realm = creds.realm;
        } else {
            realm = s->req_to;
        }
        authzid = (char *) malloc(sizeof(char) * (strlen(creds.authnid) + strlen(realm) + 2));
        sprintf(authzid, "%s@%s", creds.authnid, realm);
        creds.authzid = authzid;
    }

    /* proceed stream to authenticated state */
    sx_auth(s, method, creds.authzid);

    free(method);
    if(authzid) free(authzid);
}
Beispiel #5
0
/** make the stream authenticated second time round */
static void _sx_sasl_stream(sx_t s, sx_plugin_t p) {
    Gsasl_session *sd = (Gsasl_session *) s->plugin_data[p->index];

    /* do nothing the first time */
    if(sd == NULL)
        return;

    /* are we auth'd? */
    if(NULL == gsasl_property_fast(sd, GSASL_AUTHID)) {
        _sx_debug(ZONE, "not auth'd, not advancing to auth'd state yet");
        return;
    }

    /* otherwise, its auth time */
    _sx_sasl_open(s, sd);
}
Beispiel #6
0
int
callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop)
{
  int rc = GSASL_NO_CALLBACK;

  switch (prop)
    {
    case GSASL_ANONYMOUS_TOKEN:
      if (args_info.anonymous_token_arg == NULL)
	args_info.anonymous_token_arg =
	  readutf8line ("Enter anonymous token (e.g., email address): ");

      gsasl_property_set (sctx, GSASL_ANONYMOUS_TOKEN,
			  args_info.anonymous_token_arg);

      rc = GSASL_OK;
      break;

    case GSASL_CB_TLS_UNIQUE:
      if (!args_info.no_cb_flag && b64cbtlsunique == NULL
	  && args_info.hostname_arg == NULL)
	b64cbtlsunique =
	  readutf8line ("Enter base64 encoded tls-unique channel binding: ");
      if (!args_info.no_cb_flag && b64cbtlsunique && *b64cbtlsunique)
	gsasl_property_set (sctx, prop, b64cbtlsunique);
      rc = GSASL_OK;
      break;

    case GSASL_PASSWORD:
      if (args_info.password_arg == NULL)
	args_info.password_arg = readutf8pass ("Enter password: "******"Enter passcode: ");

      gsasl_property_set (sctx, GSASL_PASSCODE, args_info.passcode_arg);

      rc = GSASL_OK;
      break;

    case GSASL_AUTHID:
      if (args_info.authentication_id_arg == NULL)
	{
#if HAVE_GETPWUID
	  uid_t uid;
	  struct passwd *pw;

	  uid = getuid ();
	  pw = getpwuid (uid);

	  if (pw && pw->pw_name)
	    {
	      printf ("Using system username `%s' as "
		      "authentication identity.\n", pw->pw_name);
	      args_info.authentication_id_arg = xstrdup (pw->pw_name);
	    }
	  else
#endif
	    args_info.authentication_id_arg =
	      readutf8line ("Enter authentication ID: ");
	}

      gsasl_property_set (sctx, GSASL_AUTHID,
			  args_info.authentication_id_arg);
      rc = GSASL_OK;
      break;

    case GSASL_AUTHZID:
      gsasl_property_set (sctx, GSASL_AUTHZID,
			  args_info.authorization_id_arg);
      rc = GSASL_OK;
      break;

    case GSASL_SERVICE:
      if (args_info.service_arg == NULL)
	args_info.service_arg =
	  readutf8line ("Enter GSSAPI service name (e.g. \"imap\"): ");

      gsasl_property_set (sctx, GSASL_SERVICE, args_info.service_arg);

      rc = GSASL_OK;
      break;

    case GSASL_HOSTNAME:
      if (args_info.hostname_arg == NULL)
	args_info.hostname_arg = readutf8line ("Enter hostname of server: ");

      gsasl_property_set (sctx, GSASL_HOSTNAME, args_info.hostname_arg);

      rc = GSASL_OK;
      break;

    case GSASL_REALM:
      if (args_info.realm_arg == NULL)
	args_info.realm_arg =
	  readutf8line ("Enter realm of server (optional): ");

      if (args_info.realm_arg && *args_info.realm_arg)
	gsasl_property_set (sctx, GSASL_REALM, args_info.realm_arg);

      rc = GSASL_OK;
      break;

    case GSASL_QOP:
      if (args_info.quality_of_protection_arg == NULL)
	args_info.quality_of_protection_arg = readutf8line
	  ("Enter quality of protection (optional, e.g. 'qop-int'): ");
      if (args_info.quality_of_protection_arg
	  && *args_info.quality_of_protection_arg)
	gsasl_property_set (sctx, GSASL_QOP,
			    args_info.quality_of_protection_arg);
      rc = GSASL_OK;
      break;

    case GSASL_VALIDATE_GSSAPI:
      {
	char *str;
	printf ("Authzid: %s\nDisplay Name: %s\n",
		gsasl_property_fast (sctx, GSASL_AUTHZID),
		gsasl_property_fast (sctx, GSASL_GSSAPI_DISPLAY_NAME));
	str = readutf8line ("Validate GSS-API user? (y/n) ");
	if (strcmp (str, "y") == 0 || strcmp (str, "Y") == 0)
	  rc = GSASL_OK;
	else
	  rc = GSASL_AUTHENTICATION_ERROR;
	free (str);
      }
      break;

    case GSASL_SCRAM_SALTED_PASSWORD:
    case GSASL_SCRAM_ITER:
    case GSASL_SCRAM_SALT:
      break;

    case GSASL_SAML20_IDP_IDENTIFIER:
      {
	char *str = readutf8line ("Enter SAML authentication identifier "
				  "(e.g. \"http://example.org/\"): ");

	gsasl_property_set (sctx, GSASL_SAML20_IDP_IDENTIFIER, str);

	rc = GSASL_OK;
      }
      break;

    case GSASL_SAML20_AUTHENTICATE_IN_BROWSER:
      {
	const char *url = gsasl_property_get (sctx, GSASL_SAML20_REDIRECT_URL);

	printf ("Proceed to this URL to authenticate using SAML 2.0:\n%s\n",
		url);

	rc = GSASL_OK;
      }
      break;

    case GSASL_OPENID20_AUTHENTICATE_IN_BROWSER:
      {
	const char *url = gsasl_property_get (sctx,
					      GSASL_OPENID20_REDIRECT_URL);

	printf ("Proceed to this URL to authenticate using OpenID 2.0:\n%s\n",
		url);

	rc = GSASL_OK;
      }
      break;

    default:
      fprintf (stderr,
	       "warning: mechanism requested unsupported property `%d'\n",
	       prop);
      break;
    }

  return rc;
}
Beispiel #7
0
static int
cb (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop)
{
  int rc = GSASL_NO_CALLBACK;
  int i = 0, j = 0;

  if (gsasl_callback_hook_get (ctx))
    i = *(int *) gsasl_callback_hook_get (ctx);
  if (gsasl_session_hook_get (sctx))
    j = *(int *) gsasl_session_hook_get (sctx);

  if (j < 0 || j > 5)
    fail ("j out of bounds: %d\n", j);

  switch (prop)
    {
    case GSASL_AUTHID:
      gsasl_property_set (sctx, prop, sasltv[i].authid);
      rc = GSASL_OK;
      break;

    case GSASL_AUTHZID:
      gsasl_property_set (sctx, prop, sasltv[i].authzid);
      rc = GSASL_OK;
      break;

    case GSASL_PASSWORD:
      gsasl_property_set (sctx, prop, sasltv[i].password);
      rc = GSASL_OK;
      break;

    case GSASL_ANONYMOUS_TOKEN:
      gsasl_property_set (sctx, prop, sasltv[i].anonymous);
      rc = GSASL_OK;
      break;

    case GSASL_SERVICE:
      rc = GSASL_OK;
      break;

    case GSASL_PASSCODE:
      gsasl_property_set (sctx, prop, sasltv[i].passcode);
      rc = GSASL_OK;
      break;

    case GSASL_SUGGESTED_PIN:
    case GSASL_PIN:
      {
	const char *suggestion =
	  gsasl_property_fast (sctx, GSASL_SUGGESTED_PIN);
	if (suggestion && sasltv[i].suggestpin
	    && strcmp (suggestion, sasltv[i].suggestpin) != 0)
	  return GSASL_AUTHENTICATION_ERROR;

	if ((suggestion == NULL && sasltv[i].suggestpin != NULL) ||
	    (suggestion != NULL && sasltv[i].suggestpin == NULL))
	  return GSASL_AUTHENTICATION_ERROR;

	gsasl_property_set (sctx, prop, sasltv[i].pin);
	rc = GSASL_OK;
      }

    case GSASL_REALM:
      break;

    case GSASL_VALIDATE_EXTERNAL:
      rc = GSASL_OK;
      break;

    case GSASL_VALIDATE_ANONYMOUS:
      if (strcmp (sasltv[i].anonymous,
		  gsasl_property_fast (sctx, GSASL_ANONYMOUS_TOKEN)) == 0)
	rc = GSASL_OK;
      else
	rc = GSASL_AUTHENTICATION_ERROR;
      break;

    case GSASL_VALIDATE_SECURID:
      {
	const char *passcode = gsasl_property_fast (sctx, GSASL_PASSCODE);
	const char *pin = gsasl_property_fast (sctx, GSASL_PIN);

	if (strcmp (passcode, sasltv[i].passcode) != 0)
	  return GSASL_AUTHENTICATION_ERROR;

	if (sasltv[i].securidrc == GSASL_SECURID_SERVER_NEED_NEW_PIN)
	  {
	    rc = sasltv[i].securidrc;
	    sasltv[i].securidrc = GSASL_OK;

	    if (sasltv[i].suggestpin)
	      {
		gsasl_property_set (sctx, GSASL_SUGGESTED_PIN,
				    sasltv[i].suggestpin);
	      }
	  }
	else if (sasltv[i].securidrc ==
		 GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE)
	  {
	    rc = sasltv[i].securidrc;
	    sasltv[i].securidrc = GSASL_OK;
	  }
	else
	  {
	    rc = sasltv[i].securidrc;

	    if (pin && sasltv[i].pin && strcmp (pin, sasltv[i].pin) != 0)
	      return GSASL_AUTHENTICATION_ERROR;

	    if ((pin == NULL && sasltv[i].pin != NULL) ||
		(pin != NULL && sasltv[i].pin == NULL))
	      return GSASL_AUTHENTICATION_ERROR;
	  }
      }
      break;

    default:
      printf ("Unknown property %d\n", prop);
      break;
    }

  return rc;
}