Exemplo n.º 1
0
static int
cb_validate(Gsasl *ctx, Gsasl_session *sctx)
{
    int rc;
    struct sasl_data *pdata = gsasl_callback_hook_get(ctx);
    const char *authid = gsasl_property_get(sctx, GSASL_AUTHID);
    const char *pass = gsasl_property_get(sctx, GSASL_PASSWORD);
    char *dbpass;

    if (!authid)
	return GSASL_NO_AUTHID;
    if (!pass)
	return GSASL_NO_PASSWORD;

    rc = dico_udb_check_password(user_db, authid, pass);
    if (rc == ENOSYS) {
        if (dico_udb_get_password(user_db, authid, &dbpass)) {
	    dico_log(L_ERR, 0,
		     _("failed to get password for `%s' from the database"),
		     authid);
	    return GSASL_AUTHENTICATION_ERROR;
	}
	rc = dicod_check_password(dbpass, pass);
	free(dbpass);
    }
    if (rc == 0) {
	pdata->username = xstrdup(authid);
	return GSASL_OK;
    } 
    return GSASL_AUTHENTICATION_ERROR;
}
Exemplo n.º 2
0
/* Get service, hostname and authorization identity from application,
   import the GSS-API name, and initialize the channel binding data.
   Return GSASL_OK on success or an error code. */
static int
prepare (Gsasl_session * sctx, _gsasl_gs2_client_state * state)
{
  const char *service = gsasl_property_get (sctx, GSASL_SERVICE);
  const char *hostname = gsasl_property_get (sctx, GSASL_HOSTNAME);
  const char *authzid = gsasl_property_get (sctx, GSASL_AUTHZID);
  gss_buffer_desc bufdesc;
  OM_uint32 maj_stat, min_stat;

  if (!service)
    return GSASL_NO_SERVICE;
  if (!hostname)
    return GSASL_NO_HOSTNAME;

  bufdesc.length = asprintf ((char **) &bufdesc.value, "%s@%s",
			     service, hostname);
  if (bufdesc.length <= 0 || bufdesc.value == NULL)
    return GSASL_MALLOC_ERROR;

  maj_stat = gss_import_name (&min_stat, &bufdesc,
			      GSS_C_NT_HOSTBASED_SERVICE, &state->service);
  free (bufdesc.value);
  if (GSS_ERROR (maj_stat))
    return GSASL_GSSAPI_IMPORT_NAME_ERROR;

  if (authzid)
    {
      char *escaped_authzid = escape_authzid (authzid);

      if (!escaped_authzid)
	return GSASL_MALLOC_ERROR;

      state->cb.application_data.length
	= asprintf ((char **) &state->cb.application_data.value,
		    "n,a=%s,", escaped_authzid);

      free (escaped_authzid);
    }
  else
    {
      state->cb.application_data.value = strdup ("n,,");
      state->cb.application_data.length = 3;
    }

  if (state->cb.application_data.length <= 0
      || state->cb.application_data.value == NULL)
    return GSASL_MALLOC_ERROR;

  return GSASL_OK;
}
Exemplo n.º 3
0
static int
callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop)
{
  int rc = GSASL_NO_CALLBACK;

  /* Get user info from user. */

  switch (prop)
    {
    case GSASL_SAML20_IDP_IDENTIFIER:
      gsasl_property_set (sctx, prop, "https://saml.example.org/");
      rc = GSASL_OK;
      break;

    case GSASL_SAML20_AUTHENTICATE_IN_BROWSER:
      printf ("client got redirect URL: %s\n",
	      gsasl_property_get (sctx, GSASL_SAML20_REDIRECT_URL));
      rc = GSASL_OK;
      break;

    default:
      printf ("Unknown property %d!  Don't worry.\n", prop);
      break;
    }

  return rc;
}
Exemplo n.º 4
0
int
_gsasl_login_client_step (Gsasl_session * sctx,
			  void *mech_data,
			  const char *input, size_t input_len,
			  char **output, size_t * output_len)
{
  struct _Gsasl_login_client_state *state = mech_data;
  const char *p;
  int res;

  switch (state->step)
    {
    case 0:
      p = gsasl_property_get (sctx, GSASL_AUTHID);
      if (!p)
	return GSASL_NO_AUTHID;

      *output = strdup (p);
      *output_len = strlen (p);

      state->step++;
      res = GSASL_NEEDS_MORE;
      break;

    case 1:
      p = gsasl_property_get (sctx, GSASL_PASSWORD);
      if (!p)
	return GSASL_NO_PASSWORD;

      *output = strdup (p);
      *output_len = strlen (*output);

      state->step++;
      res = GSASL_OK;
      break;

    default:
      res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
      break;
    }

  return res;
}
Exemplo n.º 5
0
Arquivo: server.c Projeto: cktan/tool2
static int
scram_start (Gsasl_session * sctx, void **mech_data, int plus)
{
  struct scram_server_state *state;
  char buf[MAX (SNONCE_ENTROPY_BYTES, DEFAULT_SALT_BYTES)];
  const char *p;
  int rc;

  state = (struct scram_server_state *) calloc (sizeof (*state), 1);
  if (state == NULL)
    return GSASL_MALLOC_ERROR;

  state->plus = plus;

  rc = gsasl_nonce (buf, SNONCE_ENTROPY_BYTES);
  if (rc != GSASL_OK)
    goto end;

  rc = gsasl_base64_to (buf, SNONCE_ENTROPY_BYTES, &state->snonce, NULL);
  if (rc != GSASL_OK)
    goto end;

  rc = gsasl_nonce (buf, DEFAULT_SALT_BYTES);
  if (rc != GSASL_OK)
    goto end;

  rc = gsasl_base64_to (buf, DEFAULT_SALT_BYTES, &state->sf.salt, NULL);
  if (rc != GSASL_OK)
    goto end;

  p = gsasl_property_get (sctx, GSASL_CB_TLS_UNIQUE);
  if (plus && !p)
    {
      rc = GSASL_NO_CB_TLS_UNIQUE;
      goto end;
    }
  if (p)
    {
      rc = gsasl_base64_from (p, strlen (p), &state->cbtlsunique,
			      &state->cbtlsuniquelen);
      if (rc != GSASL_OK)
	goto end;
    }

  *mech_data = state;

  return GSASL_OK;

end:
  free (state->sf.salt);
  free (state->snonce);
  free (state);
  return rc;
}
Exemplo n.º 6
0
int
_gsasl_external_client_step (Gsasl_session * sctx,
			     void *mech_data,
			     const char *input, size_t input_len,
			     char **output, size_t * output_len)
{
  const char *p;

  p = gsasl_property_get (sctx, GSASL_AUTHZID);
  if (!p)
    p = "";

  *output = strdup (p);
  if (!*output)
    return GSASL_MALLOC_ERROR;
  *output_len = strlen (p);

  return GSASL_OK;
}
Exemplo n.º 7
0
int
_gsasl_anonymous_client_step (Gsasl_session * sctx,
			      void *mech_data,
			      const char *input, size_t input_len,
			      char **output, size_t * output_len)
{
  const char *p;

  p = gsasl_property_get (sctx, GSASL_ANONYMOUS_TOKEN);
  if (!p)
    return GSASL_NO_ANONYMOUS_TOKEN;

  *output = strdup (p);
  if (!*output)
    return GSASL_MALLOC_ERROR;
  *output_len = strlen (p);

  return GSASL_OK;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
Arquivo: server.c Projeto: cktan/tool2
int
_gsasl_scram_sha1_server_step (Gsasl_session * sctx,
			       void *mech_data,
			       const char *input,
			       size_t input_len,
			       char **output, size_t * output_len)
{
  struct scram_server_state *state = mech_data;
  int res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
  int rc;

  *output = NULL;
  *output_len = 0;

  switch (state->step)
    {
    case 0:
      {
	if (input_len == 0)
	  return GSASL_NEEDS_MORE;

	if (scram_parse_client_first (input, input_len, &state->cf) < 0)
	  return GSASL_MECHANISM_PARSE_ERROR;

	/* In PLUS server mode, we require use of channel bindings. */
	if (state->plus && state->cf.cbflag != 'p')
	  return GSASL_AUTHENTICATION_ERROR;

	/* In non-PLUS mode, but where have channel bindings data (and
	   thus advertised PLUS) we reject a client 'y' cbflag. */
	if (!state->plus
	    && state->cbtlsuniquelen > 0 && state->cf.cbflag == 'y')
	  return GSASL_AUTHENTICATION_ERROR;

	/* Check that username doesn't fail SASLprep. */
	{
	  char *tmp;
	  rc = gsasl_saslprep (state->cf.username, GSASL_ALLOW_UNASSIGNED,
			       &tmp, NULL);
	  if (rc != GSASL_OK || *tmp == '\0')
	    return GSASL_AUTHENTICATION_ERROR;
	  gsasl_free (tmp);
	}

	{
	  const char *p;

	  /* Save "gs2-header" and "message-bare" for next step. */
	  p = memchr (input, ',', input_len);
	  if (!p)
	    return GSASL_AUTHENTICATION_ERROR;
	  p++;
	  p = memchr (p, ',', input_len - (p - input));
	  if (!p)
	    return GSASL_AUTHENTICATION_ERROR;
	  p++;

	  state->gs2header = malloc (p - input + 1);
	  if (!state->gs2header)
	    return GSASL_MALLOC_ERROR;
	  memcpy (state->gs2header, input, p - input);
	  state->gs2header[p - input] = '\0';

	  state->cfmb_str = malloc (input_len - (p - input) + 1);
	  if (!state->cfmb_str)
	    return GSASL_MALLOC_ERROR;
	  memcpy (state->cfmb_str, p, input_len - (p - input));
	  state->cfmb_str[input_len - (p - input)] = '\0';
	}

	/* Create new nonce. */
	{
	  size_t cnlen = strlen (state->cf.client_nonce);

	  state->sf.nonce = malloc (cnlen + SNONCE_ENTROPY_BYTES + 1);
	  if (!state->sf.nonce)
	    return GSASL_MALLOC_ERROR;

	  memcpy (state->sf.nonce, state->cf.client_nonce, cnlen);
	  memcpy (state->sf.nonce + cnlen, state->snonce,
		  SNONCE_ENTROPY_BYTES);
	  state->sf.nonce[cnlen + SNONCE_ENTROPY_BYTES] = '\0';
	}

	gsasl_property_set (sctx, GSASL_AUTHID, state->cf.username);
	gsasl_property_set (sctx, GSASL_AUTHZID, state->cf.authzid);

	{
	  const char *p = gsasl_property_get (sctx, GSASL_SCRAM_ITER);
	  if (p)
	    state->sf.iter = strtoul (p, NULL, 10);
	  if (!p || state->sf.iter == 0 || state->sf.iter == ULONG_MAX)
	    state->sf.iter = 4096;
	}

	{
	  const char *p = gsasl_property_get (sctx, GSASL_SCRAM_SALT);
	  if (p)
	    {
	      free (state->sf.salt);
	      state->sf.salt = strdup (p);
	    }
	}

	rc = scram_print_server_first (&state->sf, &state->sf_str);
	if (rc != 0)
	  return GSASL_MALLOC_ERROR;

	*output = strdup (state->sf_str);
	if (!*output)
	  return GSASL_MALLOC_ERROR;
	*output_len = strlen (*output);

	state->step++;
	return GSASL_NEEDS_MORE;
	break;
      }

    case 1:
      {
	if (scram_parse_client_final (input, input_len, &state->cl) < 0)
	  return GSASL_MECHANISM_PARSE_ERROR;

	if (strcmp (state->cl.nonce, state->sf.nonce) != 0)
	  return GSASL_AUTHENTICATION_ERROR;

	/* Base64 decode the c= field and check that it matches
	   client-first.  Also check channel binding data. */
	{
	  size_t len;

	  rc = gsasl_base64_from (state->cl.cbind, strlen (state->cl.cbind),
				  &state->cbind, &len);
	  if (rc != 0)
	    return rc;

	  if (state->cf.cbflag == 'p')
	    {
	      if (len < strlen (state->gs2header))
		return GSASL_AUTHENTICATION_ERROR;

	      if (memcmp (state->cbind, state->gs2header,
			  strlen (state->gs2header)) != 0)
		return GSASL_AUTHENTICATION_ERROR;

	      if (len - strlen (state->gs2header) != state->cbtlsuniquelen)
		return GSASL_AUTHENTICATION_ERROR;

	      if (memcmp (state->cbind + strlen (state->gs2header),
			  state->cbtlsunique, state->cbtlsuniquelen) != 0)
		return GSASL_AUTHENTICATION_ERROR;
	    }
	  else
	    {
	      if (len != strlen (state->gs2header))
		return GSASL_AUTHENTICATION_ERROR;

	      if (memcmp (state->cbind, state->gs2header, len) != 0)
		return GSASL_AUTHENTICATION_ERROR;
	    }
	}

	/* Base64 decode client proof and check that length matches
	   SHA-1 size. */
	{
	  size_t len;

	  rc = gsasl_base64_from (state->cl.proof, strlen (state->cl.proof),
				  &state->clientproof, &len);
	  if (rc != 0)
	    return rc;
	  if (len != 20)
	    return GSASL_MECHANISM_PARSE_ERROR;
	}

	{
	  const char *p;

	  /* Get StoredKey and ServerKey */
	  if ((p = gsasl_property_get (sctx, GSASL_PASSWORD)))
	    {
	      Gc_rc err;
	      char *salt;
	      size_t saltlen;
	      char saltedpassword[20];
	      char *clientkey;
	      char *preppasswd;

	      rc = gsasl_saslprep (p, 0, &preppasswd, NULL);
	      if (rc != GSASL_OK)
		return rc;

	      rc = gsasl_base64_from (state->sf.salt, strlen (state->sf.salt),
				      &salt, &saltlen);
	      if (rc != 0)
		{
		  gsasl_free (preppasswd);
		  return rc;
		}

	      /* SaltedPassword := Hi(password, salt) */
	      err = gc_pbkdf2_sha1 (preppasswd, strlen (preppasswd),
				    salt, saltlen,
				    state->sf.iter, saltedpassword, 20);
	      gsasl_free (preppasswd);
	      gsasl_free (salt);
	      if (err != GC_OK)
		return GSASL_MALLOC_ERROR;

	      /* ClientKey := HMAC(SaltedPassword, "Client Key") */
#define CLIENT_KEY "Client Key"
	      rc = gsasl_hmac_sha1 (saltedpassword, 20,
				    CLIENT_KEY, strlen (CLIENT_KEY),
				    &clientkey);
	      if (rc != 0)
		return rc;

	      /* StoredKey := H(ClientKey) */
	      rc = gsasl_sha1 (clientkey, 20, &state->storedkey);
	      free (clientkey);
	      if (rc != 0)
		return rc;

	      /* ServerKey := HMAC(SaltedPassword, "Server Key") */
#define SERVER_KEY "Server Key"
	      rc = gsasl_hmac_sha1 (saltedpassword, 20,
				    SERVER_KEY, strlen (SERVER_KEY),
				    &state->serverkey);
	      if (rc != 0)
		return rc;
	    }
	  else
	    return GSASL_NO_PASSWORD;

	  /* Compute AuthMessage */
	  {
	    size_t len;
	    int n;

	    /* Get client-final-message-without-proof. */
	    p = memmem (input, input_len, ",p=", 3);
	    if (!p)
	      return GSASL_MECHANISM_PARSE_ERROR;
	    len = p - input;

	    n = asprintf (&state->authmessage, "%s,%.*s,%.*s",
			  state->cfmb_str,
			  (int) strlen (state->sf_str), state->sf_str,
			  (int) len, input);
	    if (n <= 0 || !state->authmessage)
	      return GSASL_MALLOC_ERROR;
	  }

	  /* Check client proof. */
	  {
	    char *clientsignature;
	    char *maybe_storedkey;

	    /* ClientSignature := HMAC(StoredKey, AuthMessage) */
	    rc = gsasl_hmac_sha1 (state->storedkey, 20,
				  state->authmessage,
				  strlen (state->authmessage),
				  &clientsignature);
	    if (rc != 0)
	      return rc;

	    /* ClientKey := ClientProof XOR ClientSignature */
	    memxor (clientsignature, state->clientproof, 20);

	    rc = gsasl_sha1 (clientsignature, 20, &maybe_storedkey);
	    free (clientsignature);
	    if (rc != 0)
	      return rc;

	    rc = memcmp (state->storedkey, maybe_storedkey, 20);
	    free (maybe_storedkey);
	    if (rc != 0)
	      return GSASL_AUTHENTICATION_ERROR;
	  }

	  /* Generate server verifier. */
	  {
	    char *serversignature;

	    /* ServerSignature := HMAC(ServerKey, AuthMessage) */
	    rc = gsasl_hmac_sha1 (state->serverkey, 20,
				  state->authmessage,
				  strlen (state->authmessage),
				  &serversignature);
	    if (rc != 0)
	      return rc;

	    rc = gsasl_base64_to (serversignature, 20,
				  &state->sl.verifier, NULL);
	    free (serversignature);
	    if (rc != 0)
	      return rc;
	  }
	}

	rc = scram_print_server_final (&state->sl, output);
	if (rc != 0)
	  return GSASL_MALLOC_ERROR;
	*output_len = strlen (*output);

	state->step++;
	return GSASL_OK;
	break;
      }

    default:
      break;
    }

  return res;
}
Exemplo n.º 10
0
static int
callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop)
{
    int rc = GSASL_OK;
    struct sasl_data *pdata;
    const char *user;
    char *string;

    switch (prop) {
    case GSASL_PASSWORD:
	pdata = gsasl_callback_hook_get(ctx);
	user = pdata->username;
	if (!user) {
	    user = gsasl_property_get(sctx, GSASL_AUTHID);
	    if (!user) {
		dico_log(L_ERR, 0, _("user name not supplied"));
		return GSASL_NO_AUTHID;
	    }
	    pdata->username = user;
	}
	if (dico_udb_get_password(user_db, user, &string)) {
	    dico_log(L_ERR, 0,
		     _("failed to get password for `%s' from the database"),
		     user);
	    return GSASL_NO_PASSWORD;
	} 
	gsasl_property_set(sctx, prop, string);
	free(string);
	break;

    case GSASL_SERVICE:
	gsasl_property_set(sctx, prop, sasl_service);
	break;

    case GSASL_REALM:
	gsasl_property_set(sctx, prop, sasl_realm ? sasl_realm : hostname);
	break;

    case GSASL_HOSTNAME:
	gsasl_property_set(sctx, prop, hostname);
	break;

    case GSASL_VALIDATE_SIMPLE:
	rc = cb_validate(ctx, sctx);
	break;

#if 0
    FIXME:
    case GSASL_VALIDATE_EXTERNAL:
    case GSASL_VALIDATE_SECURID:
#endif

    case GSASL_VALIDATE_ANONYMOUS:
	pdata = gsasl_callback_hook_get(ctx);
	user = gsasl_property_get(sctx, GSASL_ANONYMOUS_TOKEN);
	pdata->username = user;
	pdata->anon = 1;
	break;

    case GSASL_VALIDATE_GSSAPI:
	pdata = gsasl_callback_hook_get(ctx);
	user = gsasl_property_get(sctx, GSASL_AUTHZID);
	pdata->username = user;
	break;
	
    default:
	rc = GSASL_NO_CALLBACK;
	/*dico_log(L_NOTICE, 0, _("Unsupported callback property %d"), prop);*/
	break;
    }

    return rc;
}
Exemplo n.º 11
0
int
_gsasl_gssapi_client_step (Gsasl_session * sctx,
			   void *mech_data,
			   const char *input, size_t input_len,
			   char **output, size_t * output_len)
{
  _Gsasl_gssapi_client_state *state = mech_data;
  char clientwrap[4];
  gss_qop_t serverqop;
  gss_buffer_desc bufdesc, bufdesc2;
  gss_buffer_t buf = GSS_C_NO_BUFFER;
  OM_uint32 maj_stat, min_stat;
  int conf_state;
  int res;
  const char *p;

  if (state->service == NULL)
    {
      const char *service, *hostname;

      service = gsasl_property_get (sctx, GSASL_SERVICE);
      if (!service)
	return GSASL_NO_SERVICE;

      hostname = gsasl_property_get (sctx, GSASL_HOSTNAME);
      if (!hostname)
	return GSASL_NO_HOSTNAME;

      /* FIXME: Use asprintf. */

      bufdesc.length = strlen (service) + 1 + strlen (hostname) + 1;
      bufdesc.value = malloc (bufdesc.length);
      if (bufdesc.value == NULL)
	return GSASL_MALLOC_ERROR;

      sprintf (bufdesc.value, "%s@%s", service, hostname);

      maj_stat = gss_import_name (&min_stat, &bufdesc,
				  GSS_C_NT_HOSTBASED_SERVICE,
				  &state->service);
      free (bufdesc.value);
      if (GSS_ERROR (maj_stat))
	return GSASL_GSSAPI_IMPORT_NAME_ERROR;
    }

  switch (state->step)
    {
    case 1:
      bufdesc.length = input_len;
      bufdesc.value = (void *) input;
      buf = &bufdesc;
      /* fall through */

    case 0:
      bufdesc2.length = 0;
      bufdesc2.value = NULL;
      maj_stat = gss_init_sec_context (&min_stat,
				       GSS_C_NO_CREDENTIAL,
				       &state->context,
				       state->service,
				       GSS_C_NO_OID,
				       GSS_C_MUTUAL_FLAG |
				       GSS_C_REPLAY_FLAG |
				       GSS_C_SEQUENCE_FLAG |
				       GSS_C_INTEG_FLAG |
				       GSS_C_CONF_FLAG,
				       0,
				       GSS_C_NO_CHANNEL_BINDINGS,
				       buf, NULL, &bufdesc2, NULL, NULL);
      if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED)
	return GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR;

      *output_len = bufdesc2.length;
      *output = malloc (*output_len);
      if (!*output)
	return GSASL_MALLOC_ERROR;
      memcpy (*output, bufdesc2.value, bufdesc2.length);

      if (maj_stat == GSS_S_COMPLETE)
	state->step = 2;
      else
	state->step = 1;

      maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
      if (maj_stat != GSS_S_COMPLETE)
	return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;

      res = GSASL_NEEDS_MORE;
      break;

    case 2:
      /* [RFC 2222 section 7.2.1]:
         The client passes this token to GSS_Unwrap and interprets the
         first octet of resulting cleartext as a bit-mask specifying
         the security layers supported by the server and the second
         through fourth octets as the maximum size output_message to
         send to the server.  The client then constructs data, with
         the first octet containing the bit-mask specifying the
         selected security layer, the second through fourth octets
         containing in network byte order the maximum size
         output_message the client is able to receive, and the
         remaining octets containing the authorization identity.  The
         client passes the data to GSS_Wrap with conf_flag set to
         FALSE, and responds with the generated output_message.  The
         client can then consider the server authenticated. */

      bufdesc.length = input_len;
      bufdesc.value = (void *) input;
      maj_stat = gss_unwrap (&min_stat, state->context, &bufdesc,
			     &bufdesc2, &conf_state, &serverqop);
      if (GSS_ERROR (maj_stat))
	return GSASL_GSSAPI_UNWRAP_ERROR;

      if (bufdesc2.length != 4)
	return GSASL_MECHANISM_PARSE_ERROR;

      memcpy (clientwrap, bufdesc2.value, 4);

      maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
      if (GSS_ERROR (maj_stat))
	return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;

#if 0
      /* FIXME: Fix qop. */
      if (cb_qop)
	state->qop = cb_qop (sctx, serverqop);

      if ((state->qop & serverqop) == 0)
	/*  Server does not support what user wanted. */
	return GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR;
#endif

      /* FIXME: Fix maxbuf. */

      p = gsasl_property_get (sctx, GSASL_AUTHID);
      if (!p)
	return GSASL_NO_AUTHID;

      bufdesc.length = 4 + strlen (p);
      bufdesc.value = malloc (bufdesc.length);
      if (!bufdesc.value)
	return GSASL_MALLOC_ERROR;

      {
	char *q = bufdesc.value;
	q[0] = state->qop;
	memcpy (q + 1, clientwrap + 1, 3);
	memcpy (q + 4, p, strlen (p));
      }

      maj_stat = gss_wrap (&min_stat, state->context, 0, GSS_C_QOP_DEFAULT,
			   &bufdesc, &conf_state, &bufdesc2);
      free (bufdesc.value);
      if (GSS_ERROR (maj_stat))
	return GSASL_GSSAPI_WRAP_ERROR;

      *output_len = bufdesc2.length;
      *output = malloc (bufdesc2.length);
      if (!*output)
	return GSASL_MALLOC_ERROR;

      memcpy (*output, bufdesc2.value, bufdesc2.length);

      maj_stat = gss_release_buffer (&min_stat, &bufdesc2);
      if (GSS_ERROR (maj_stat))
	return GSASL_GSSAPI_RELEASE_BUFFER_ERROR;

      state->step++;
      res = GSASL_OK;
      break;

    default:
      res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
      break;
    }

  return res;
}
Exemplo n.º 12
0
Arquivo: client.c Projeto: cktan/tool2
int
_gsasl_openid20_client_step (Gsasl_session * sctx,
			     void *mech_data,
			     const char *input, size_t input_len,
			     char **output, size_t * output_len)
{
  struct openid20_client_state *state = mech_data;
  int res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;

  switch (state->step)
    {
    case 0:
      {
	const char *authzid = gsasl_property_get (sctx, GSASL_AUTHZID);
	const char *authid = gsasl_property_get (sctx, GSASL_AUTHID);

	if (!authid || !*authid)
	  return GSASL_NO_AUTHID;

	res = _gsasl_gs2_generate_header (false, 'n', NULL, authzid,
					  strlen (authid), authid,
					  output, output_len);
	if (res != GSASL_OK)
	  return res;

	res = GSASL_NEEDS_MORE;
	state->step++;
      }
      break;

    case 1:
      {
	gsasl_property_set_raw (sctx, GSASL_OPENID20_REDIRECT_URL,
				input, input_len);

	res = gsasl_callback (NULL, sctx,
			      GSASL_OPENID20_AUTHENTICATE_IN_BROWSER);
	if (res != GSASL_OK)
	  return res;

	*output_len = 1;
	*output = strdup ("=");
	if (!*output)
	  return GSASL_MALLOC_ERROR;

	res = GSASL_OK;
	state->step++;
      }
      break;

      /* This step is optional.  The server could have approved
         authentication already.  Alternatively, it wanted to send
         some SREGs or error data and we end up here. */
    case 2:
      {
	gsasl_property_set_raw (sctx, GSASL_OPENID20_OUTCOME_DATA,
				input, input_len);

	/* In the case of failures, the response MUST follow this
	   syntax:

	   outcome_data = "openid.error" "=" sreg_val *( "," sregp_avp )

	   [RFC4422] Section 3.6 explicitly prohibits additional information in
	   an unsuccessful authentication outcome.  Therefore, the openid.error
	   and openid.error_code are to be sent as an additional challenge in
	   the event of an unsuccessful outcome.  In this case, as the protocol
	   is lock step,  the client will follow with an additional exchange
	   containing "=", after which the server will respond with an
	   application-level outcome.
	 */

#define ERR_PREFIX "openid.error="
	if (input_len > strlen (ERR_PREFIX)
	    && strncmp (ERR_PREFIX, input, strlen (ERR_PREFIX)) == 0)
	  {
	    *output_len = 1;
	    *output = strdup ("=");
	    if (!*output)
	      return GSASL_MALLOC_ERROR;

	    res = GSASL_NEEDS_MORE;
	  }
	else
	  {
	    *output_len = 0;
	    *output = NULL;

	    res = GSASL_OK;
	  }

	state->step++;
      }
      break;

    default:
      break;
    }

  return res;
}
Exemplo n.º 13
0
static int
callback (Gsasl * ctx, Gsasl_session * sctx, Gsasl_property prop)
{
  int rc = GSASL_NO_CALLBACK;
  struct cfg *cfg = gsasl_callback_hook_get (ctx);

  switch (prop)
    {
    case GSASL_SAML20_REDIRECT_URL:
      {
	FILE *fh;
	char *reqid, *redirect_url, *tmp;
	size_t n = 0;
	const char *idp =
	  gsasl_property_get (sctx, GSASL_SAML20_IDP_IDENTIFIER);

	/* User did not provide a SAML IdP identifier. */
	if (!idp)
	  return GSASL_AUTHENTICATION_ERROR;

	/* Sanitize input. */
	if (strcmp (idp, ".") == 0 || strcmp (idp, "..") == 0)
	  return GSASL_AUTHENTICATION_ERROR;
	for (n = 0; idp[n]; n++)
	  if (!((idp[n] >= 'a' && idp[n] <= 'z')
		|| (idp[n] >= 'A' && idp[n] <= 'Z')
		|| (idp[n] >= '0' && idp[n] <= '9') || idp[n] == '.'))
	    {
	      printf ("Cannot handle identifier (%ld): %s\n",
		      (unsigned long) n, idp);
	      return GSASL_AUTHENTICATION_ERROR;
	    }

	/* Run helper to generate SAML AuthnRequest.   Read out request ID. */
	rc = asprintf (&tmp, "gsasl-saml20-request %s %s %s %s "
		       "%s/%s/idp-metadata.xml",
		       cfg->state_path, cfg->sp_metadata,
		       cfg->sp_key, cfg->sp_cert, cfg->cfg_path, idp);
	if (rc <= 0)
	  return GSASL_AUTHENTICATION_ERROR;
	fh = popen (tmp, "r");
	free (tmp);
	if (!fh)
	  {
	    perror ("popen");
	    return GSASL_AUTHENTICATION_ERROR;
	  }
	reqid = NULL;
	n = 0;
	if (getline (&reqid, &n, fh) <= 0)
	  {
	    perror ("getline");
	    return GSASL_AUTHENTICATION_ERROR;
	  }
	if (reqid[strlen (reqid) - 1] == '\n')
	  reqid[strlen (reqid) - 1] = '\0';
	if (reqid[strlen (reqid) - 1] == '\r')
	  reqid[strlen (reqid) - 1] = '\0';
	rc = pclose (fh);
	if (rc != 0)
	  {
	    perror ("pclose");
	    return GSASL_AUTHENTICATION_ERROR;
	  }

	/* Read URL to redirect to.  Written by gsasl-saml20-request. */
	rc = asprintf (&tmp, "%s/%s/redirect_url", cfg->state_path, reqid);
	if (rc <= 0)
	  return GSASL_AUTHENTICATION_ERROR;
	fh = fopen (tmp, "r");
	free (tmp);
	if (!fh)
	  {
	    perror ("fopen");
	    return GSASL_AUTHENTICATION_ERROR;
	  }
	redirect_url = NULL;
	n = 0;
	if (getline (&redirect_url, &n, fh) <= 0)
	  {
	    perror ("getline");
	    return GSASL_AUTHENTICATION_ERROR;
	  }
	rc = fclose (fh);
	if (rc != 0)
	  {
	    perror ("fclose");
	    return GSASL_AUTHENTICATION_ERROR;
	  }

	/* We are done */
	gsasl_session_hook_set (sctx, reqid);
	gsasl_property_set (sctx, prop, redirect_url);

	printf ("read id: %s\n", reqid);
	printf ("url: %s\n", redirect_url);

	free (redirect_url);

	return GSASL_OK;
      }
      break;

    case GSASL_VALIDATE_SAML20:
      {
	time_t start = time (NULL);
	char *id = (char *) gsasl_session_hook_get (sctx);
	char *tmp, *line;
	size_t n;
	FILE *fh;

	if (!id)
	  return GSASL_AUTHENTICATION_ERROR;

	do
	  {
	    sleep (1);

	    rc = asprintf (&tmp, "%s/%s/success", cfg->state_path, id);
	    if (rc <= 0)
	      return GSASL_AUTHENTICATION_ERROR;
	    fh = fopen (tmp, "r");
	    free (tmp);
	    if (!fh)
	      {
		rc = asprintf (&tmp, "%s/%s/fail", cfg->state_path, id);
		if (rc <= 0)
		  return GSASL_AUTHENTICATION_ERROR;
		fh = fopen (tmp, "r");
		free (tmp);
		if (!fh)
		  {
		    puts ("waiting");
		    continue;
		  }
		rc = fclose (fh);
		if (rc != 0)
		  {
		    perror ("fclose");
		    return GSASL_AUTHENTICATION_ERROR;
		  }

		return GSASL_AUTHENTICATION_ERROR;
	      }

	    rc = fclose (fh);
	    if (rc != 0)
	      {
		perror ("fclose");
		return GSASL_AUTHENTICATION_ERROR;
	      }

	    rc = asprintf (&tmp, "%s/%s/subject", cfg->state_path, id);
	    if (rc <= 0)
	      return GSASL_AUTHENTICATION_ERROR;
	    fh = fopen (tmp, "r");
	    free (tmp);
	    if (!fh)
	      {
		perror ("fopen");
		return GSASL_AUTHENTICATION_ERROR;
	      }

	    line = NULL;
	    n = 0;
	    if (getline (&line, &n, fh) <= 0)
	      {
		perror ("getline");
		return GSASL_AUTHENTICATION_ERROR;
	      }

	    printf ("subject: %s\n", line);
	    gsasl_property_set (sctx, GSASL_AUTHID, line);
	    free (line);

	    rc = fclose (fh);
	    if (rc != 0)
	      {
		perror ("fclose");
		return GSASL_AUTHENTICATION_ERROR;
	      }

	    free (id);

	    return GSASL_OK;
	  }
	while (time (NULL) - start < 30);

	printf ("timeout\n");

	return GSASL_AUTHENTICATION_ERROR;
      }
      break;

    case GSASL_PASSWORD:
      gsasl_property_set (sctx, prop, "sesam");
      rc = GSASL_OK;
      break;

    default:
      /* You may want to log (at debug verbosity level) that an
         unknown property was requested here, possibly after filtering
         known rejected property requests. */
      break;
    }

  return rc;
}
Exemplo n.º 14
0
int
_gsasl_ntlm_client_step (Gsasl_session * sctx,
                         void *mech_data,
                         const char *input, size_t input_len,
                         char **output, size_t * output_len)
{
    _Gsasl_ntlm_state *state = mech_data;
    tSmbNtlmAuthRequest request;
    tSmbNtlmAuthChallenge challenge;
    tSmbNtlmAuthResponse response;
    const char *domain = gsasl_property_get (sctx, GSASL_REALM);
    const char *authid = gsasl_property_get (sctx, GSASL_AUTHID);
    const char *password;
    int res;

    if (!authid)
        return GSASL_NO_AUTHID;

    switch (state->step)
    {
    case 0:
        /* Isn't this just the IMAP continuation char?  Not part of SASL mech.
           if (input_len != 1 && *input != '+')
           return GSASL_MECHANISM_PARSE_ERROR; */

        buildSmbNtlmAuthRequest (&request, authid, domain);

        *output_len = SmbLength (&request);
        *output = malloc (*output_len);
        if (!*output)
            return GSASL_MALLOC_ERROR;
        memcpy (*output, &request, *output_len);

        /* dumpSmbNtlmAuthRequest(stdout, &request); */

        state->step++;
        res = GSASL_NEEDS_MORE;
        break;

    case 1:
        if (input_len > sizeof (challenge))
            return GSASL_MECHANISM_PARSE_ERROR;

        /* Hand crafted challenge for parser testing:
           TlRMTVNTUAAAAAAAAAAAAAAAAAAAAGFiY2RlZmdoMDEyMzQ1Njc4ODY2NDQwMTIz */

        memcpy (&challenge, input, input_len);

        password = gsasl_property_get (sctx, GSASL_PASSWORD);
        if (!password)
            return GSASL_NO_PASSWORD;

        buildSmbNtlmAuthResponse (&challenge, &response, authid, password);

        *output_len = SmbLength (&response);
        *output = malloc (*output_len);
        if (!*output)
            return GSASL_MALLOC_ERROR;
        memcpy (*output, &response, *output_len);

        /* dumpSmbNtlmAuthResponse(stdout, &response); */

        state->step++;
        res = GSASL_OK;
        break;

    default:
        res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
        break;
    }

    return res;
}
Exemplo n.º 15
0
Arquivo: server.c Projeto: cktan/tool2
int
_gsasl_securid_server_step (Gsasl_session * sctx,
			    void *mech_data,
			    const char *input, size_t input_len,
			    char **output, size_t * output_len)
{
  const char *authorization_id = NULL;
  const char *authentication_id = NULL;
  const char *passcode = NULL;
  const char *suggestedpin;
  char *pin = NULL;
  int res;
  size_t len;

  if (input_len == 0)
    {
      *output_len = 0;
      *output = NULL;
      return GSASL_NEEDS_MORE;
    }

  authorization_id = input;
  authentication_id = memchr (input, '\0', input_len - 1);
  if (authentication_id)
    {
      authentication_id++;
      passcode = memchr (authentication_id, '\0',
			 input_len - strlen (authorization_id) - 1 - 1);
      if (passcode)
	{
	  passcode++;
	  pin = memchr (passcode, '\0', input_len -
			strlen (authorization_id) - 1 -
			strlen (authentication_id) - 1 - 1);
	  if (pin)
	    {
	      pin++;
	      if (pin && !*pin)
		pin = NULL;
	    }
	}
    }

  if (passcode == NULL)
    return GSASL_MECHANISM_PARSE_ERROR;

  gsasl_property_set (sctx, GSASL_AUTHID, authentication_id);
  gsasl_property_set (sctx, GSASL_AUTHZID, authorization_id);
  gsasl_property_set (sctx, GSASL_PASSCODE, passcode);
  if (pin)
    gsasl_property_set (sctx, GSASL_PIN, pin);
  else
    gsasl_property_set (sctx, GSASL_PIN, NULL);

  res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_SECURID);
  switch (res)
    {
    case GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE:
      *output = strdup (PASSCODE);
      if (!*output)
	return GSASL_MALLOC_ERROR;
      *output_len = strlen (PASSCODE);
      res = GSASL_NEEDS_MORE;
      break;

    case GSASL_SECURID_SERVER_NEED_NEW_PIN:
      suggestedpin = gsasl_property_get (sctx, GSASL_SUGGESTED_PIN);
      if (suggestedpin)
	len = strlen (suggestedpin);
      else
	len = 0;
      *output_len = strlen (PIN) + len;
      *output = malloc (*output_len);
      if (!*output)
	return GSASL_MALLOC_ERROR;
      memcpy (*output, PIN, strlen (PIN));
      if (suggestedpin)
	memcpy (*output + strlen (PIN), suggestedpin, len);
      res = GSASL_NEEDS_MORE;
      break;

    default:
      *output_len = 0;
      *output = NULL;
      break;
    }

  return res;
}
Exemplo n.º 16
0
int
_gsasl_gssapi_server_start (Gsasl_session * sctx, void **mech_data)
{
  _Gsasl_gssapi_server_state *state;
  OM_uint32 maj_stat, min_stat;
  gss_name_t server;
  gss_buffer_desc bufdesc;
  const char *service;
  const char *hostname;

  service = gsasl_property_get (sctx, GSASL_SERVICE);
  if (!service)
    return GSASL_NO_SERVICE;

  hostname = gsasl_property_get (sctx, GSASL_HOSTNAME);
  if (!hostname)
    return GSASL_NO_HOSTNAME;

  /* FIXME: Use asprintf. */

  bufdesc.length = strlen (service) + strlen ("@") + strlen (hostname) + 1;
  bufdesc.value = malloc (bufdesc.length);
  if (bufdesc.value == NULL)
    return GSASL_MALLOC_ERROR;

  sprintf (bufdesc.value, "%s@%s", service, hostname);

  state = (_Gsasl_gssapi_server_state *) malloc (sizeof (*state));
  if (state == NULL)
    {
      free (bufdesc.value);
      return GSASL_MALLOC_ERROR;
    }

  maj_stat = gss_import_name (&min_stat, &bufdesc, GSS_C_NT_HOSTBASED_SERVICE,
			      &server);
  free (bufdesc.value);
  if (GSS_ERROR (maj_stat))
    {
      free (state);
      return GSASL_GSSAPI_IMPORT_NAME_ERROR;
    }

  maj_stat = gss_acquire_cred (&min_stat, server, 0,
			       GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
			       &state->cred, NULL, NULL);
  gss_release_name (&min_stat, &server);

  if (GSS_ERROR (maj_stat))
    {
      free (state);
      return GSASL_GSSAPI_ACQUIRE_CRED_ERROR;
    }

  state->step = 0;
  state->context = GSS_C_NO_CONTEXT;
  state->client = NULL;
  *mech_data = state;

  return GSASL_OK;
}
Exemplo n.º 17
0
Arquivo: server.c Projeto: cktan/tool2
int
_gsasl_login_server_step (Gsasl_session * sctx,
			  void *mech_data,
			  const char *input, size_t input_len,
			  char **output, size_t * output_len)
{
  struct _Gsasl_login_server_state *state = mech_data;
  int res;

  switch (state->step)
    {
    case 0:
      *output = strdup (CHALLENGE_USERNAME);
      if (!*output)
	return GSASL_MALLOC_ERROR;
      *output_len = strlen (CHALLENGE_USERNAME);

      state->step++;
      res = GSASL_NEEDS_MORE;
      break;

    case 1:
      if (input_len == 0)
	return GSASL_MECHANISM_PARSE_ERROR;

      state->username = malloc (input_len + 1);
      if (state->username == NULL)
	return GSASL_MALLOC_ERROR;

      memcpy (state->username, input, input_len);
      state->username[input_len] = '\0';

      *output = strdup (CHALLENGE_PASSWORD);
      if (!*output)
	return GSASL_MALLOC_ERROR;
      *output_len = strlen (CHALLENGE_PASSWORD);

      state->step++;
      res = GSASL_NEEDS_MORE;
      break;

    case 2:
      if (input_len == 0)
	return GSASL_MECHANISM_PARSE_ERROR;

      state->password = malloc (input_len + 1);
      if (state->password == NULL)
	return GSASL_MALLOC_ERROR;

      memcpy (state->password, input, input_len);
      state->password[input_len] = '\0';

      if (input_len != strlen (state->password))
	return GSASL_MECHANISM_PARSE_ERROR;

      gsasl_property_set (sctx, GSASL_AUTHID, state->username);
      gsasl_property_set (sctx, GSASL_PASSWORD, state->password);

      res = gsasl_callback (NULL, sctx, GSASL_VALIDATE_SIMPLE);
      if (res == GSASL_NO_CALLBACK)
	{
	  const char *key;

	  gsasl_property_set (sctx, GSASL_AUTHZID, NULL);
	  gsasl_property_set (sctx, GSASL_PASSWORD, NULL);

	  key = gsasl_property_get (sctx, GSASL_PASSWORD);

	  if (key && strlen (state->password) == strlen (key) &&
	      strcmp (state->password, key) == 0)
	    res = GSASL_OK;
	  else
	    res = GSASL_AUTHENTICATION_ERROR;
	}

      *output_len = 0;
      *output = NULL;
      state->step++;
      break;

    default:
      res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
      break;
    }

  return res;
}
Exemplo n.º 18
0
int
_gsasl_digest_md5_server_step (Gsasl_session * sctx,
                               void *mech_data,
                               const char *input,
                               size_t input_len,
                               char **output, size_t * output_len)
{
    _Gsasl_digest_md5_server_state *state = mech_data;
    int rc, res;

    *output = NULL;
    *output_len = 0;

    switch (state->step)
    {
    case 0:
        /* Set realm. */
    {
        const char *c;
        c = gsasl_property_get (sctx, GSASL_REALM);
        if (c)
        {
            state->challenge.nrealms = 1;

            state->challenge.realms =
                malloc (sizeof (*state->challenge.realms));
            if (!state->challenge.realms)
                return GSASL_MALLOC_ERROR;

            state->challenge.realms[0] = strdup (c);
            if (!state->challenge.realms[0])
                return GSASL_MALLOC_ERROR;
        }
    }

        /* Set QOP */
    {
        const char *qopstr = gsasl_property_get (sctx, GSASL_QOPS);

        if (qopstr)
        {
            int qops = digest_md5_qopstr2qops (qopstr);

            if (qops == -1)
                return GSASL_MALLOC_ERROR;

            /* We don't support confidentiality right now. */
            if (qops & DIGEST_MD5_QOP_AUTH_CONF)
                return GSASL_AUTHENTICATION_ERROR;

            if (qops)
                state->challenge.qops = qops;
        }
    }

        /* FIXME: cipher, maxbuf, more realms. */

        /* Create challenge. */
    *output = digest_md5_print_challenge (&state->challenge);
    if (!*output)
        return GSASL_AUTHENTICATION_ERROR;

    *output_len = strlen (*output);
    state->step++;
    res = GSASL_NEEDS_MORE;
    break;

    case 1:
        if (digest_md5_parse_response (input, input_len, &state->response) < 0)
            return GSASL_MECHANISM_PARSE_ERROR;

        /* Make sure response is consistent with challenge. */
        if (digest_md5_validate (&state->challenge, &state->response) < 0)
            return GSASL_MECHANISM_PARSE_ERROR;

        /* Store properties, from the client response. */
        if (state->response.utf8)
        {
            gsasl_property_set (sctx, GSASL_AUTHID, state->response.username);
            gsasl_property_set (sctx, GSASL_REALM, state->response.realm);
        }
        else
        {
            /* Client provided username/realm in ISO-8859-1 form,
               convert it to UTF-8 since the library is all-UTF-8. */
            char *tmp;

            tmp = latin1toutf8 (state->response.username);
            if (!tmp)
                return GSASL_MALLOC_ERROR;
            gsasl_property_set (sctx, GSASL_AUTHID, tmp);
            free (tmp);

            tmp = latin1toutf8 (state->response.realm);
            if (!tmp)
                return GSASL_MALLOC_ERROR;
            gsasl_property_set (sctx, GSASL_REALM, tmp);
            free (tmp);
        }
        gsasl_property_set (sctx, GSASL_AUTHZID, state->response.authzid);

        /* FIXME: cipher, maxbuf.  */

        /* Compute secret. */
        {
            const char *passwd;
            const char *hashed_passwd;

            hashed_passwd =
                gsasl_property_get (sctx, GSASL_DIGEST_MD5_HASHED_PASSWORD);
            if (hashed_passwd)
            {
                if (strlen (hashed_passwd) != (DIGEST_MD5_LENGTH * 2))
                    return GSASL_AUTHENTICATION_ERROR;

                rc = _gsasl_digest_md5_set_hashed_secret (state->secret,
                        hashed_passwd);
                if (rc != GSASL_OK)
                    return rc;
            }
            else if ((passwd = gsasl_property_get (sctx, GSASL_PASSWORD)) != NULL)
            {
                char *tmp, *tmp2;

                tmp2 = utf8tolatin1ifpossible (passwd);

                rc = asprintf (&tmp, "%s:%s:%s", state->response.username,
                               state->response.realm ?
                               state->response.realm : "", tmp2);
                free (tmp2);
                if (rc < 0)
                    return GSASL_MALLOC_ERROR;

                rc = gsasl_md5 (tmp, strlen (tmp), &tmp2);
                free (tmp);
                if (rc != GSASL_OK)
                    return rc;

                memcpy (state->secret, tmp2, DIGEST_MD5_LENGTH);
                free (tmp2);
            }
            else
            {
                return GSASL_NO_PASSWORD;
            }
        }

        /* Check client response. */
        {
            char check[DIGEST_MD5_RESPONSE_LENGTH + 1];

            rc = digest_md5_hmac (check, state->secret,
                                  state->response.nonce, state->response.nc,
                                  state->response.cnonce, state->response.qop,
                                  state->response.authzid,
                                  state->response.digesturi, 0,
                                  state->response.cipher,
                                  state->kic, state->kis, state->kcc, state->kcs);
            if (rc)
                return GSASL_AUTHENTICATION_ERROR;

            if (strcmp (state->response.response, check) != 0)
                return GSASL_AUTHENTICATION_ERROR;
        }

        /* Create finish token. */
        rc = digest_md5_hmac (state->finish.rspauth, state->secret,
                              state->response.nonce, state->response.nc,
                              state->response.cnonce, state->response.qop,
                              state->response.authzid,
                              state->response.digesturi, 1,
                              state->response.cipher, NULL, NULL, NULL, NULL);
        if (rc)
            return GSASL_AUTHENTICATION_ERROR;

        *output = digest_md5_print_finish (&state->finish);
        if (!*output)
            return GSASL_MALLOC_ERROR;

        *output_len = strlen (*output);

        state->step++;
        res = GSASL_OK;
        break;

    default:
        res = GSASL_MECHANISM_CALLED_TOO_MANY_TIMES;
        break;
    }

    return res;
}
Exemplo n.º 19
0
int
_gsasl_cram_md5_client_step (Gsasl_session * sctx,
			     void *mech_data,
			     const char *input, size_t input_len,
			     char **output, size_t * output_len)
{
  char response[CRAM_MD5_DIGEST_LEN];
  const char *p;
  size_t len;
  char *tmp;
  char *authid;
  int rc;

  if (input_len == 0)
    {
      *output_len = 0;
      *output = NULL;
      return GSASL_NEEDS_MORE;
    }

  p = gsasl_property_get (sctx, GSASL_AUTHID);
  if (!p)
    return GSASL_NO_AUTHID;

  /* XXX Use query strings here?  Specification is unclear. */
  rc = gsasl_saslprep (p, GSASL_ALLOW_UNASSIGNED, &authid, NULL);
  if (rc != GSASL_OK)
    return rc;

  p = gsasl_property_get (sctx, GSASL_PASSWORD);
  if (!p)
    {
      free (authid);
      return GSASL_NO_PASSWORD;
    }

  /* XXX Use query strings here?  Specification is unclear. */
  rc = gsasl_saslprep (p, GSASL_ALLOW_UNASSIGNED, &tmp, NULL);
  if (rc != GSASL_OK)
    {
      free (authid);
      return rc;
    }

  cram_md5_digest (input, input_len, tmp, strlen (tmp), response);

  free (tmp);

  len = strlen (authid);

  *output_len = len + strlen (" ") + CRAM_MD5_DIGEST_LEN;
  *output = malloc (*output_len);
  if (!*output)
    {
      free (authid);
      return GSASL_MALLOC_ERROR;
    }

  memcpy (*output, authid, len);
  (*output)[len++] = ' ';
  memcpy (*output + len, response, CRAM_MD5_DIGEST_LEN);

  free (authid);

  return GSASL_OK;
}