Exemple #1
0
void pni_process_init(pn_transport_t *transport, const char *mechanism, const pn_bytes_t *recv)
{
    pni_sasl_t *sasl = transport->sasl;

    int result = pni_wrap_server_start(sasl, mechanism, recv);
    if (result==SASL_OK) {
        // We need to filter out a supplied mech in in the inclusion list
        // as the client could have used a mech that we support, but that
        // wasn't on the list we sent.
        if (!pni_included_mech(sasl->included_mechanisms, pn_bytes(strlen(mechanism), mechanism))) {
            sasl_conn_t *cyrus_conn = (sasl_conn_t*)sasl->impl_context;
            sasl_seterror(cyrus_conn, 0, "Client mechanism not in mechanism inclusion list.");
            result = SASL_FAIL;
        }
    }
    pni_process_server_result(transport, result);
}
Exemple #2
0
/* Convert a SASL authcid or authzid into a DN. Store the DN in an
 * auxiliary property, so that we can refer to it in sasl_authorize
 * without interfering with anything else. Also, the SASL username
 * buffer is constrained to 256 characters, and our DNs could be
 * much longer (SLAP_LDAPDN_MAXLEN, currently set to 8192)
 */
static int
slap_sasl_canonicalize(
	sasl_conn_t *sconn,
	void *context,
	const char *in,
	unsigned inlen,
	unsigned flags,
	const char *user_realm,
	char *out,
	unsigned out_max,
	unsigned *out_len)
{
	Connection *conn = (Connection *)context;
	struct propctx *props = sasl_auxprop_getctx( sconn );
	struct propval auxvals[ SLAP_SASL_PROP_COUNT ] = { { 0 } };
	struct berval dn;
	int rc, which;
	const char *names[2];
	struct berval	bvin;

	*out_len = 0;

	Debug( LDAP_DEBUG_ARGS, "SASL Canonicalize [conn=%ld]: %s=\"%s\"\n",
		conn ? (long) conn->c_connid : -1L,
		(flags & SASL_CU_AUTHID) ? "authcid" : "authzid",
		in ? in : "<empty>");

	/* If name is too big, just truncate. We don't care, we're
	 * using DNs, not the usernames.
	 */
	if ( inlen > out_max )
		inlen = out_max-1;

	/* This is a Simple Bind using SPASSWD. That means the in-directory
	 * userPassword of the Binding user already points at SASL, so it
	 * cannot be used to actually satisfy a password comparison. Just
	 * ignore it, some other mech will process it.
	 */
	if ( !conn->c_sasl_bindop ||
		conn->c_sasl_bindop->orb_method != LDAP_AUTH_SASL ) goto done;

	/* See if we need to add request, can only do it once */
	prop_getnames( props, slap_propnames, auxvals );
	if ( !auxvals[0].name )
		prop_request( props, slap_propnames );

	if ( flags & SASL_CU_AUTHID )
		which = SLAP_SASL_PROP_AUTHCLEN;
	else
		which = SLAP_SASL_PROP_AUTHZLEN;

	/* Need to store the Connection for auxprop_lookup */
	if ( !auxvals[SLAP_SASL_PROP_CONN].values ) {
		names[0] = slap_propnames[SLAP_SASL_PROP_CONN];
		names[1] = NULL;
		prop_set( props, names[0], (char *)&conn, sizeof( conn ) );
	}
		
	/* Already been here? */
	if ( auxvals[which].values )
		goto done;

	/* Normally we require an authzID to have a u: or dn: prefix.
	 * However, SASL frequently gives us an authzID that is just
	 * an exact copy of the authcID, without a prefix. We need to
	 * detect and allow this condition. If SASL calls canonicalize
	 * with SASL_CU_AUTHID|SASL_CU_AUTHZID this is a no-brainer.
	 * But if it's broken into two calls, we need to remember the
	 * authcID so that we can compare the authzID later. We store
	 * the authcID temporarily in conn->c_sasl_dn. We necessarily
	 * finish Canonicalizing before Authorizing, so there is no
	 * conflict with slap_sasl_authorize's use of this temp var.
	 *
	 * The SASL EXTERNAL mech is backwards from all the other mechs,
	 * it does authzID before the authcID. If we see that authzID
	 * has already been done, don't do anything special with authcID.
	 */
	if ( flags == SASL_CU_AUTHID && !auxvals[SLAP_SASL_PROP_AUTHZ].values ) {
		conn->c_sasl_dn.bv_val = (char *) in;
		conn->c_sasl_dn.bv_len = 0;
	} else if ( flags == SASL_CU_AUTHZID && conn->c_sasl_dn.bv_val ) {
		rc = strcmp( in, conn->c_sasl_dn.bv_val );
		conn->c_sasl_dn.bv_val = NULL;
		/* They were equal, no work needed */
		if ( !rc ) goto done;
	}

	bvin.bv_val = (char *)in;
	bvin.bv_len = inlen;
	rc = slap_sasl_getdn( conn, NULL, &bvin, (char *)user_realm, &dn,
		(flags & SASL_CU_AUTHID) ? SLAP_GETDN_AUTHCID : SLAP_GETDN_AUTHZID );
	if ( rc != LDAP_SUCCESS ) {
		sasl_seterror( sconn, 0, ldap_err2string( rc ) );
		return SASL_NOAUTHZ;
	}

	names[0] = slap_propnames[which];
	names[1] = NULL;
	prop_set( props, names[0], (char *)&dn.bv_len, sizeof( dn.bv_len ) );

	which++;
	names[0] = slap_propnames[which];
	prop_set( props, names[0], dn.bv_val, dn.bv_len );

	Debug( LDAP_DEBUG_ARGS, "SASL Canonicalize [conn=%ld]: %s=\"%s\"\n",
		conn ? (long) conn->c_connid : -1L, names[0]+1,
		dn.bv_val ? dn.bv_val : "<EMPTY>" );

	/* Not needed any more, SASL has copied it */
	if ( conn && conn->c_sasl_bindop )
		conn->c_sasl_bindop->o_tmpfree( dn.bv_val, conn->c_sasl_bindop->o_tmpmemctx );

done:
	AC_MEMCPY( out, in, inlen );
	out[inlen] = '\0';

	*out_len = inlen;

	return SASL_OK;
}
Exemple #3
0
static int
slap_sasl_authorize(
	sasl_conn_t *sconn,
	void *context,
	char *requested_user,
	unsigned rlen,
	char *auth_identity,
	unsigned alen,
	const char *def_realm,
	unsigned urlen,
	struct propctx *props)
{
	Connection *conn = (Connection *)context;
	/* actually:
	 *	(SLAP_SASL_PROP_COUNT - 1)	because we skip "conn",
	 *	+ 1				for NULL termination?
	 */
	struct propval auxvals[ SLAP_SASL_PROP_COUNT ] = { { 0 } };
	struct berval authcDN, authzDN = BER_BVNULL;
	int rc;

	/* Simple Binds don't support proxy authorization, ignore it */
	if ( !conn->c_sasl_bindop ||
		conn->c_sasl_bindop->orb_method != LDAP_AUTH_SASL ) return SASL_OK;

	Debug( LDAP_DEBUG_ARGS, "SASL proxy authorize [conn=%ld]: "
		"authcid=\"%s\" authzid=\"%s\"\n",
		conn ? (long) conn->c_connid : -1L, auth_identity, requested_user );
	if ( conn->c_sasl_dn.bv_val ) {
		BER_BVZERO( &conn->c_sasl_dn );
	}

	/* Skip SLAP_SASL_PROP_CONN */
	prop_getnames( props, slap_propnames+1, auxvals );
	
	/* Should not happen */
	if ( !auxvals[0].values ) {
		sasl_seterror( sconn, 0, "invalid authcid" );
		return SASL_NOAUTHZ;
	}

	AC_MEMCPY( &authcDN.bv_len, auxvals[0].values[0], sizeof(authcDN.bv_len) );
	authcDN.bv_val = auxvals[1].values ? (char *)auxvals[1].values[0] : NULL;
	conn->c_sasl_dn = authcDN;

	/* Nothing to do if no authzID was given */
	if ( !auxvals[2].name || !auxvals[2].values ) {
		goto ok;
	}
	
	AC_MEMCPY( &authzDN.bv_len, auxvals[2].values[0], sizeof(authzDN.bv_len) );
	authzDN.bv_val = auxvals[3].values ? (char *)auxvals[3].values[0] : NULL;

	rc = slap_sasl_authorized( conn->c_sasl_bindop, &authcDN, &authzDN );
	if ( rc != LDAP_SUCCESS ) {
		Debug( LDAP_DEBUG_TRACE, "SASL Proxy Authorize [conn=%ld]: "
			"proxy authorization disallowed (%d)\n",
			conn ? (long) conn->c_connid : -1L, rc, 0 );

		sasl_seterror( sconn, 0, "not authorized" );
		return SASL_NOAUTHZ;
	}

	/* FIXME: we need yet another dup because slap_sasl_getdn()
	 * is using the bind operation slab */
	ber_dupbv( &conn->c_sasl_authz_dn, &authzDN );

ok:
	if (conn->c_sasl_bindop) {
		Statslog( LDAP_DEBUG_STATS,
			"%s BIND authcid=\"%s\" authzid=\"%s\"\n",
			conn->c_sasl_bindop->o_log_prefix, 
			auth_identity, requested_user, 0, 0 );
	}

	Debug( LDAP_DEBUG_TRACE, "SASL Authorize [conn=%ld]: "
		" proxy authorization allowed authzDN=\"%s\"\n",
		conn ? (long) conn->c_connid : -1L, 
		authzDN.bv_val ? authzDN.bv_val : "", 0 );
	return SASL_OK;
} 
Exemple #4
0
/* Need to make sure that
 *  *) The authnid is permitted to become the given authzid
 *  *) The authnid is included in the given authreg systems DB
 */
static int _sx_sasl_proxy_policy(sasl_conn_t *conn, void *ctx, const char *requested_user, int rlen, const char *auth_identity, int alen, const char *realm, int urlen, struct propctx *propctx) {
    _sx_sasl_data_t sd = (_sx_sasl_data_t) ctx;
    struct sx_sasl_creds_st creds = {NULL, NULL, NULL, NULL};
    char *buf, *c;
    size_t len;
    int ret;

    sasl_getprop(conn, SASL_MECHNAME, (const void **) &buf);
    if (strncmp(buf, "ANONYMOUS", 10) == 0) {
        /* If they're anonymous, their ID comes from us, so it must be OK! */
        return SASL_OK;
    } else {
        /* This will break with clients that give requested user as a JID,
         * where requested_user != auth_identity */
        if (!requested_user || !auth_identity || rlen == 0 || alen==0) {
          sasl_seterror(conn, 0,
                        "Bad identities provided");
          return SASL_BADAUTH;
      }

      /* No guarantee that realm is NULL terminated - so make a terminated
         * version before we do anything */

      /* XXX - Do we also need to check if realm contains NULL values, 
       *       and complain if it does?
         */

      buf = malloc(urlen + 1);
      strncpy(buf, realm?realm:"", urlen);
      buf[urlen] = '\0';
      creds.realm = buf;

      /* By this point, SASL's default canon_user plugin has appended the
         * realm to both the auth_identity, and the requested_user. This
         * isn't what we want.
         *   auth_identity should be a bare username
         *   requested_user should be a JID
         *
         * We can't just remove everything after the '@' as some mechanisms
         * (such as GSSAPI) use the @ to denote users in foreign realms.
         */

      buf = malloc(alen + 1);
      strncpy(buf, auth_identity, alen);
      buf[alen] = '\0';
      c = strrchr(buf, '@');
      if (c && strcmp(c+1, creds.realm) == 0)
            *c = '\0';
      creds.authnid = buf;

      /* Now, we need to turn requested_user into a JID 
         * (if it isn't already)
       *
       * XXX - This will break with s2s SASL, where the authzid is a domain
       */
      len = rlen;
      if (sd->stream->req_to)
          len+=strlen(sd->stream->req_to) + 2;
      buf = malloc(len + 1);
      strncpy(buf, requested_user, rlen);
      buf[rlen] = '\0';
      c = strrchr(buf, '@');
      if (c && strcmp(c + 1, creds.realm) == 0)
          *c = '\0';
      if (sd->stream->req_to && strchr(buf, '@') == 0) {
          strcat(buf, "@");
          strcat(buf, sd->stream->req_to);
      }
      creds.authzid = buf;

          /* If we start being fancy and allow auth_identity to be different from
           * requested_user, then this will need to be changed to permit it!
           */
        ret = (sd->ctx->cb)(sx_sasl_cb_CHECK_AUTHZID, &creds, NULL, sd->stream, sd->ctx->cbarg);

      free((void *)creds.authnid);
      free((void *)creds.authzid);
      free((void *)creds.realm);

      if (ret == sx_sasl_ret_OK) {
          return SASL_OK;
      } else {
          sasl_seterror(conn, 0, "Requested identity not permitted for authorization identity");
          return SASL_BADAUTH;
      }
    }
}