Exemple #1
0
int
LDAP_CALL
ldap_extended_operation(
    LDAP		*ld,
    const char		*exoid,
    const struct berval	*exdata,
    LDAPControl		**serverctrls,
    LDAPControl		**clientctrls,
    int			*msgidp
)
{
	BerElement	*ber;
	int		rc, msgid;

	/*
	 * the ldapv3 extended operation request looks like this:
	 *
	 *	ExtendedRequest ::= [APPLICATION 23] SEQUENCE {
	 *		requestName	LDAPOID,
	 *		requestValue	OCTET STRING
	 *	}
	 *
	 * all wrapped up in an LDAPMessage sequence.
	 */

	LDAPDebug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 );

	if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
		return( LDAP_PARAM_ERROR );
	}


	/* only ldapv3 or higher can do extended operations */
	if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) {
		rc = LDAP_NOT_SUPPORTED;
		LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
		return( rc );
	}

	if ( msgidp == NULL || exoid == NULL || *exoid == '\0' ) {
		rc = LDAP_PARAM_ERROR;
		LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
		return( rc );
	}

	LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK );
	msgid = ++ld->ld_msgid;
	LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK );

#if 0
	if ( ld->ld_cache_on && ld->ld_cache_extendedop != NULL ) {
		LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );
		if ( (rc = (ld->ld_cache_extendedop)( ld, msgid,
		    LDAP_REQ_EXTENDED, exoid, cred )) != 0 ) {
			LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
			return( rc );
		}
		LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
	}
#endif

	/* create a message to send */
	if (( rc = nsldapi_alloc_ber_with_options( ld, &ber ))
	    != LDAP_SUCCESS ) {
		return( rc );
	}

	/* fill it in */
	if ( ber_printf( ber, "{it{tsto}", msgid, LDAP_REQ_EXTENDED,
	    LDAP_TAG_EXOP_REQ_OID, exoid, LDAP_TAG_EXOP_REQ_VALUE,
	    exdata->bv_val, (int)exdata->bv_len /* XXX lossy cast */ ) == -1 ) {
		rc = LDAP_ENCODING_ERROR;
		LDAP_SET_LDERRNO( ld, rc, NULL, NULL );
		ber_free( ber, 1 );
		return( rc );
	}

	if (( rc = nsldapi_put_controls( ld, serverctrls, 1, ber ))
	    != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return( rc );
	}

	/* send the message */
	rc = nsldapi_send_initial_request( ld, msgid, LDAP_REQ_EXTENDED, NULL,
		ber );
	*msgidp = rc;
	return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS );
}
Exemple #2
0
static int
vc_create_response(
	void *conn,
	int resultCode,
	const char *diagnosticMessage,
	struct berval *servercred,
	struct berval *authzid,
	LDAPControl **ctrls,
	struct berval **val )
{
	BerElementBuffer berbuf;
	BerElement *ber = (BerElement *)&berbuf;
	struct berval bv;
	int rc;

	assert( val != NULL );

	*val = NULL;

	ber_init2( ber, NULL, LBER_USE_DER );

	(void)ber_printf( ber, "{is" /*}*/ , resultCode, diagnosticMessage ? diagnosticMessage : "" );

	if ( conn ) {
		struct berval cookie;

		cookie.bv_len = sizeof( conn );
		cookie.bv_val = (char *)&conn;
		(void)ber_printf( ber, "tO", 0, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, &cookie ); 
	}

	if ( servercred ) {
		ber_printf( ber, "tO", LDAP_TAG_EXOP_VERIFY_CREDENTIALS_SCREDS, servercred ); 
	}

#if 0
	if ( authzid ) {
		ber_printf( ber, "tO", LDAP_TAG_EXOP_VERIFY_CREDENTIALS_AUTHZID, authzid ); 
	}
#endif

	if ( ctrls ) {
		int c;

		rc = ber_printf( ber, "t{"/*}*/, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS );
		if ( rc == -1 ) goto done;

		for ( c = 0; ctrls[c] != NULL; c++ ) {
			rc = ber_printf( ber, "{s" /*}*/, ctrls[c]->ldctl_oid );

			if ( ctrls[c]->ldctl_iscritical ) {
				rc = ber_printf( ber, "b", (ber_int_t)ctrls[c]->ldctl_iscritical ) ;
				if ( rc == -1 ) goto done;
			}

			if ( ctrls[c]->ldctl_value.bv_val != NULL ) {
				rc = ber_printf( ber, "O", &ctrls[c]->ldctl_value ); 
				if( rc == -1 ) goto done;
			}

			rc = ber_printf( ber, /*{*/"N}" );
			if ( rc == -1 ) goto done;
		}

		rc = ber_printf( ber, /*{*/"N}" );
		if ( rc == -1 ) goto done;
	}

	ber_printf( ber, /*{*/ "}" );

	rc = ber_flatten2( ber, &bv, 0 );

	*val = ber_bvdup( &bv );

done:;
	ber_free_buf( ber );

	return rc;
}
Exemple #3
0
int
ldap_pvt_put_filter( BerElement *ber, const char *str_in )
{
	int rc;
	char	*freeme;
	char	*str;
	char	*next;
	int	parens, balance, escape;

	/*
	 * A Filter looks like this (RFC 4511 as extended by RFC 4526):
	 *     Filter ::= CHOICE {
	 *         and             [0]     SET SIZE (0..MAX) OF filter Filter,
	 *         or              [1]     SET SIZE (0..MAX) OF filter Filter,
	 *         not             [2]     Filter,
	 *         equalityMatch   [3]     AttributeValueAssertion,
	 *         substrings      [4]     SubstringFilter,
	 *         greaterOrEqual  [5]     AttributeValueAssertion,
	 *         lessOrEqual     [6]     AttributeValueAssertion,
	 *         present         [7]     AttributeDescription,
	 *         approxMatch     [8]     AttributeValueAssertion,
	 *         extensibleMatch [9]     MatchingRuleAssertion,
	 *         ... }
	 *
	 *     SubstringFilter ::= SEQUENCE {
	 *         type         AttributeDescription,
	 *         substrings   SEQUENCE SIZE (1..MAX) OF substring CHOICE {
	 *             initial          [0] AssertionValue, -- only once
	 *             any              [1] AssertionValue,
	 *             final            [2] AssertionValue  -- only once
	 *             }
	 *         }
	 *
	 *	   MatchingRuleAssertion ::= SEQUENCE {
	 *         matchingRule    [1] MatchingRuleId OPTIONAL,
	 *         type            [2] AttributeDescription OPTIONAL,
	 *         matchValue      [3] AssertionValue,
	 *         dnAttributes    [4] BOOLEAN DEFAULT FALSE }
	 *
	 * Note: tags in a CHOICE are always explicit
	 */

	Debug( LDAP_DEBUG_TRACE, "put_filter: \"%s\"\n", str_in, 0, 0 );

	freeme = LDAP_STRDUP( str_in );
	if( freeme == NULL ) return LDAP_NO_MEMORY;
	str = freeme;

	parens = 0;
	while ( *str ) {
		switch ( *str ) {
		case '(': /*')'*/
			str++;
			parens++;

			/* skip spaces */
			while( LDAP_SPACE( *str ) ) str++;

			switch ( *str ) {
			case '&':
				Debug( LDAP_DEBUG_TRACE, "put_filter: AND\n",
				    0, 0, 0 );

				str = put_complex_filter( ber, str,
				    LDAP_FILTER_AND, 0 );
				if( str == NULL ) {
					rc = -1;
					goto done;
				}

				parens--;
				break;

			case '|':
				Debug( LDAP_DEBUG_TRACE, "put_filter: OR\n",
				    0, 0, 0 );

				str = put_complex_filter( ber, str,
				    LDAP_FILTER_OR, 0 );
				if( str == NULL ) {
					rc = -1;
					goto done;
				}

				parens--;
				break;

			case '!':
				Debug( LDAP_DEBUG_TRACE, "put_filter: NOT\n",
				    0, 0, 0 );

				str = put_complex_filter( ber, str,
				    LDAP_FILTER_NOT, 0 );
				if( str == NULL ) {
					rc = -1;
					goto done;
				}

				parens--;
				break;

			case '(':
				rc = -1;
				goto done;

			default:
				Debug( LDAP_DEBUG_TRACE, "put_filter: simple\n",
				    0, 0, 0 );

				balance = 1;
				escape = 0;
				next = str;

				while ( *next && balance ) {
					if ( escape == 0 ) {
						if ( *next == '(' ) {
							balance++;
						} else if ( *next == ')' ) {
							balance--;
						}
					}

					if ( *next == '\\' && ! escape ) {
						escape = 1;
					} else {
						escape = 0;
					}

					if ( balance ) next++;
				}

				if ( balance != 0 ) {
					rc = -1;
					goto done;
				}

				*next = '\0';

				if ( put_simple_filter( ber, str ) == -1 ) {
					rc = -1;
					goto done;
				}

				*next++ = /*'('*/ ')';

				str = next;
				parens--;
				break;
			}
			break;

		case /*'('*/ ')':
			Debug( LDAP_DEBUG_TRACE, "put_filter: end\n",
				0, 0, 0 );
			if ( ber_printf( ber, /*"["*/ "]" ) == -1 ) {
				rc = -1;
				goto done;
			}
			str++;
			parens--;
			break;

		case ' ':
			str++;
			break;

		default:	/* assume it's a simple type=value filter */
			Debug( LDAP_DEBUG_TRACE, "put_filter: default\n",
				0, 0, 0 );
			next = strchr( str, '\0' );
			if ( put_simple_filter( ber, str ) == -1 ) {
				rc = -1;
				goto done;
			}
			str = next;
			break;
		}
		if ( !parens )
			break;
	}

	rc = ( parens || *str ) ? -1 : 0;

done:
	LDAP_FREE( freeme );
	return rc;
}
Exemple #4
0
static int
deref_response( Operation *op, SlapReply *rs )
{
	int rc = SLAP_CB_CONTINUE;

	if ( rs->sr_type == REP_SEARCH ) {
		BerElementBuffer berbuf;
		BerElement *ber = (BerElement *) &berbuf;
		deref_cb_t *dc = (deref_cb_t *)op->o_callback->sc_private;
		DerefSpec *ds;
		DerefRes *dr, *drhead = NULL, **drp = &drhead;
		struct berval bv = BER_BVNULL;
		int nDerefRes = 0, nDerefVals = 0, nAttrs = 0, nVals = 0;
		struct berval ctrlval;
		LDAPControl *ctrl, *ctrlsp[2];
		AccessControlState acl_state = ACL_STATE_INIT;
		static char dummy = '\0';
		Entry *ebase;
		int i;

		rc = overlay_entry_get_ov( op, &rs->sr_entry->e_nname, NULL, NULL, 0, &ebase, dc->dc_on );
		if ( rc != LDAP_SUCCESS || ebase == NULL ) {
			return SLAP_CB_CONTINUE;
		}

		for ( ds = dc->dc_ds; ds; ds = ds->ds_next ) {
			Attribute *a = attr_find( ebase->e_attrs, ds->ds_derefAttr );

			if ( a != NULL ) {
				DerefVal *dv;
				BerVarray *bva;

				if ( !access_allowed( op, rs->sr_entry, a->a_desc,
						NULL, ACL_READ, &acl_state ) )
				{
					continue;
				}

				dr = op->o_tmpcalloc( 1,
					sizeof( DerefRes ) + ( sizeof( DerefVal ) + sizeof( BerVarray * ) * ds->ds_nattrs ) * ( a->a_numvals + 1 ),
					op->o_tmpmemctx );
				dr->dr_spec = *ds;
				dv = dr->dr_vals = (DerefVal *)&dr[ 1 ];
				bva = (BerVarray *)&dv[ a->a_numvals + 1 ];

				bv.bv_len += ds->ds_derefAttr->ad_cname.bv_len;
				nAttrs++;
				nDerefRes++;

				for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) {
					Entry *e = NULL;

					dv[ i ].dv_attrVals = bva;
					bva += ds->ds_nattrs;


					if ( !access_allowed( op, rs->sr_entry, a->a_desc,
							&a->a_nvals[ i ], ACL_READ, &acl_state ) )
					{
						dv[ i ].dv_derefSpecVal.bv_val = &dummy;
						continue;
					}

					ber_dupbv_x( &dv[ i ].dv_derefSpecVal, &a->a_vals[ i ], op->o_tmpmemctx );
					bv.bv_len += dv[ i ].dv_derefSpecVal.bv_len;
					nVals++;
					nDerefVals++;

					rc = overlay_entry_get_ov( op, &a->a_nvals[ i ], NULL, NULL, 0, &e, dc->dc_on );
					if ( rc == LDAP_SUCCESS && e != NULL ) {
						int j;

						if ( access_allowed( op, e, slap_schema.si_ad_entry,
							NULL, ACL_READ, NULL ) )
						{
							for ( j = 0; j < ds->ds_nattrs; j++ ) {
								Attribute *aa;

								if ( !access_allowed( op, e, ds->ds_attributes[ j ], NULL,
									ACL_READ, &acl_state ) )
								{
									continue;
								}

								aa = attr_find( e->e_attrs, ds->ds_attributes[ j ] );
								if ( aa != NULL ) {
									unsigned k, h, last = aa->a_numvals;

									ber_bvarray_dup_x( &dv[ i ].dv_attrVals[ j ],
										aa->a_vals, op->o_tmpmemctx );

									bv.bv_len += ds->ds_attributes[ j ]->ad_cname.bv_len;

									for ( k = 0, h = 0; k < aa->a_numvals; k++ ) {
										if ( !access_allowed( op, e,
											aa->a_desc,
											&aa->a_nvals[ k ],
											ACL_READ, &acl_state ) )
										{
											op->o_tmpfree( dv[ i ].dv_attrVals[ j ][ h ].bv_val,
												op->o_tmpmemctx );
											dv[ i ].dv_attrVals[ j ][ h ] = dv[ i ].dv_attrVals[ j ][ --last ];
											BER_BVZERO( &dv[ i ].dv_attrVals[ j ][ last ] );
											continue;
										}
										bv.bv_len += dv[ i ].dv_attrVals[ j ][ h ].bv_len;
										nVals++;
										h++;
									}
									nAttrs++;
								}
							}
						}

						overlay_entry_release_ov( op, e, 0, dc->dc_on );
					}
				}

				*drp = dr;
				drp = &dr->dr_next;
			}
		}
		overlay_entry_release_ov( op, ebase, 0, dc->dc_on );

		if ( drhead == NULL ) {
			return SLAP_CB_CONTINUE;
		}

		/* cook the control value */
		bv.bv_len += nVals * sizeof(struct berval)
			+ nAttrs * sizeof(struct berval)
			+ nDerefVals * sizeof(DerefVal)
			+ nDerefRes * sizeof(DerefRes);
		bv.bv_val = op->o_tmpalloc( bv.bv_len, op->o_tmpmemctx );

		ber_init2( ber, &bv, LBER_USE_DER );
		ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );

		rc = ber_printf( ber, "{" /*}*/ );
		for ( dr = drhead; dr != NULL; dr = dr->dr_next ) {
			for ( i = 0; !BER_BVISNULL( &dr->dr_vals[ i ].dv_derefSpecVal ); i++ ) {
				int j, first = 1;

				if ( dr->dr_vals[ i ].dv_derefSpecVal.bv_val == &dummy ) {
					continue;
				}

				rc = ber_printf( ber, "{OO" /*}*/,
					&dr->dr_spec.ds_derefAttr->ad_cname,
					&dr->dr_vals[ i ].dv_derefSpecVal );
				op->o_tmpfree( dr->dr_vals[ i ].dv_derefSpecVal.bv_val, op->o_tmpmemctx );
				for ( j = 0; j < dr->dr_spec.ds_nattrs; j++ ) {
					if ( dr->dr_vals[ i ].dv_attrVals[ j ] != NULL ) {
						if ( first ) {
							rc = ber_printf( ber, "t{" /*}*/,
								(LBER_CONSTRUCTED|LBER_CLASS_CONTEXT) );
							first = 0;
						}
						rc = ber_printf( ber, "{O[W]}",
							&dr->dr_spec.ds_attributes[ j ]->ad_cname,
							dr->dr_vals[ i ].dv_attrVals[ j ] );
						op->o_tmpfree( dr->dr_vals[ i ].dv_attrVals[ j ],
							op->o_tmpmemctx );
					}
				}
				if ( !first ) {
					rc = ber_printf( ber, /*{{*/ "}N}" );
				} else {
					rc = ber_printf( ber, /*{*/ "}" );
				}
			}
		}
		rc = ber_printf( ber, /*{*/ "}" );
		if ( ber_flatten2( ber, &ctrlval, 0 ) == -1 ) {
			if ( op->o_deref == SLAP_CONTROL_CRITICAL ) {
				rc = LDAP_CONSTRAINT_VIOLATION;

			} else {
				rc = SLAP_CB_CONTINUE;
			}
			goto cleanup;
		}

		ctrl = op->o_tmpcalloc( 1,
			sizeof( LDAPControl ) + ctrlval.bv_len + 1,
			op->o_tmpmemctx );
		ctrl->ldctl_value.bv_val = (char *)&ctrl[ 1 ];
		ctrl->ldctl_oid = LDAP_CONTROL_X_DEREF;
		ctrl->ldctl_iscritical = 0;
		ctrl->ldctl_value.bv_len = ctrlval.bv_len;
		memcpy( ctrl->ldctl_value.bv_val, ctrlval.bv_val, ctrlval.bv_len );
		ctrl->ldctl_value.bv_val[ ctrl->ldctl_value.bv_len ] = '\0';

		ber_free_buf( ber );

		ctrlsp[0] = ctrl;
		ctrlsp[1] = NULL;
		slap_add_ctrls( op, rs, ctrlsp );

		rc = SLAP_CB_CONTINUE;

cleanup:;
		/* release all */
		for ( ; drhead != NULL; ) {
			DerefRes *drnext = drhead->dr_next;
			op->o_tmpfree( drhead, op->o_tmpmemctx );
			drhead = drnext;
		}

	} else if ( rs->sr_type == REP_RESULT ) {
		rc = deref_cleanup( op, rs );
	}

	return rc;
}
Exemple #5
0
/*
 * initialize the sync
 */
int
ldap_sync_init( ldap_sync_t *ls, int mode )
{
	LDAPControl	ctrl = { 0 },
			*ctrls[ 2 ];
	BerElement	*ber = NULL;
	int		rc;
	struct timeval	tv = { 0 },
			*tvp = NULL;
	LDAPMessage	*res = NULL;

#ifdef LDAP_SYNC_TRACE
	fprintf( stderr, "ldap_sync_init(%s)...\n",
		mode == LDAP_SYNC_REFRESH_AND_PERSIST ?
			"LDAP_SYNC_REFRESH_AND_PERSIST" :
			( mode == LDAP_SYNC_REFRESH_ONLY ?
				"LDAP_SYNC_REFRESH_ONLY" : "unknown" ) );
#endif /* LDAP_SYNC_TRACE */

	assert( ls != NULL );
	assert( ls->ls_ld != NULL );

	/* support both refreshOnly and refreshAndPersist */
	switch ( mode ) {
	case LDAP_SYNC_REFRESH_AND_PERSIST:
	case LDAP_SYNC_REFRESH_ONLY:
		break;

	default:
		fprintf( stderr, "ldap_sync_init: unknown mode=%d\n", mode );
		return LDAP_PARAM_ERROR;
	}

	/* check consistency of cookie and reloadHint at initial refresh */
	if ( ls->ls_cookie.bv_val == NULL && ls->ls_reloadHint != 0 ) {
		fprintf( stderr, "ldap_sync_init: inconsistent cookie/rhint\n" );
		return LDAP_PARAM_ERROR;
	}

	ctrls[ 0 ] = &ctrl;
	ctrls[ 1 ] = NULL;

	/* prepare the Sync Request control */
	ber = ber_alloc_t( LBER_USE_DER );
#ifdef LDAP_SYNC_TRACE
	fprintf( stderr, "%sber_alloc_t() %s= NULL\n",
		ber == NULL ? "!!! " : "",
		ber == NULL ? "=" : "!" );
#endif /* LDAP_SYNC_TRACE */
	if ( ber == NULL ) {
		rc = LDAP_NO_MEMORY;
		goto done;
	}

	ls->ls_refreshPhase = LDAP_SYNC_CAPI_NONE;

	if ( ls->ls_cookie.bv_val != NULL ) {
		ber_printf( ber, "{eOb}", mode,
			&ls->ls_cookie, ls->ls_reloadHint );

	} else {
		ber_printf( ber, "{eb}", mode, ls->ls_reloadHint );
	}

	rc = ber_flatten2( ber, &ctrl.ldctl_value, 0 );
#ifdef LDAP_SYNC_TRACE
	fprintf( stderr,
		"%sber_flatten2() == %d\n",
		rc ? "!!! " : "",
		rc );
#endif /* LDAP_SYNC_TRACE */
	if ( rc < 0 ) {
		rc = LDAP_OTHER;
                goto done;
        }

	/* make the control critical, as we cannot proceed without */
	ctrl.ldctl_oid = LDAP_CONTROL_SYNC;
	ctrl.ldctl_iscritical = 1;

	/* timelimit? */
	if ( ls->ls_timelimit ) {
		tv.tv_sec = ls->ls_timelimit;
		tvp = &tv;
	}

	/* actually run the search */
	rc = ldap_search_ext( ls->ls_ld,
		ls->ls_base, ls->ls_scope, ls->ls_filter,
		ls->ls_attrs, 0, ctrls, NULL,
		tvp, ls->ls_sizelimit, &ls->ls_msgid );
#ifdef LDAP_SYNC_TRACE
	fprintf( stderr,
		"%sldap_search_ext(\"%s\", %d, \"%s\") == %d\n",
		rc ? "!!! " : "",
		ls->ls_base, ls->ls_scope, ls->ls_filter, rc );
#endif /* LDAP_SYNC_TRACE */
	if ( rc != LDAP_SUCCESS ) {
		goto done;
	}

	/* initial content/content update phase */
	for ( ; ; ) {
		LDAPMessage	*msg = NULL;

		/* NOTE: this very short timeout is just to let
		 * ldap_result() yield long enough to get something */
		tv.tv_sec = 0;
		tv.tv_usec = 100000;

		rc = ldap_result( ls->ls_ld, ls->ls_msgid,
			LDAP_MSG_RECEIVED, &tv, &res );
#ifdef LDAP_SYNC_TRACE
		fprintf( stderr,
			"\t%sldap_result(%d) == %d\n",
			rc == -1 ? "!!! " : "",
			ls->ls_msgid, rc );
#endif /* LDAP_SYNC_TRACE */
		switch ( rc ) {
		case 0:
			/*
			 * timeout
			 *
			 * TODO: can do something else in the meanwhile)
			 */
			break;

		case -1:
			/* smtg bad! */
			goto done;

		default:
			for ( msg = ldap_first_message( ls->ls_ld, res );
				msg != NULL;
				msg = ldap_next_message( ls->ls_ld, msg ) )
			{
				int	refreshDone;

				switch ( ldap_msgtype( msg ) ) {
				case LDAP_RES_SEARCH_ENTRY:
					rc = ldap_sync_search_entry( ls, res );
					break;

				case LDAP_RES_SEARCH_REFERENCE:
					rc = ldap_sync_search_reference( ls, res );
					break;

				case LDAP_RES_SEARCH_RESULT:
					rc = ldap_sync_search_result( ls, res );
					goto done_search;

				case LDAP_RES_INTERMEDIATE:
					rc = ldap_sync_search_intermediate( ls, res, &refreshDone );
					if ( rc != LDAP_SUCCESS || refreshDone ) {
						goto done_search;
					}
					break;

				default:
#ifdef LDAP_SYNC_TRACE
					fprintf( stderr, "\tgot something unexpected...\n" );
#endif /* LDAP_SYNC_TRACE */

					ldap_msgfree( res );

					rc = LDAP_OTHER;
					goto done;
				}
			}
			ldap_msgfree( res );
			res = NULL;
			break;
		}
	}

done_search:;
	ldap_msgfree( res );

done:;
	if ( ber != NULL ) {
		ber_free( ber, 1 );
	}

	return rc;
}
Exemple #6
0
BerElement *
ldap_build_search_req(
	LDAP *ld,
	LDAP_CONST char *base,
	ber_int_t scope,
	LDAP_CONST char *filter,
	char **attrs,
	ber_int_t attrsonly,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	ber_int_t timelimit,
	ber_int_t sizelimit )
{
	BerElement	*ber;
	int		err;

	/*
	 * Create the search request.  It looks like this:
	 *	SearchRequest := [APPLICATION 3] SEQUENCE {
	 *		baseObject	DistinguishedName,
	 *		scope		ENUMERATED {
	 *			baseObject	(0),
	 *			singleLevel	(1),
	 *			wholeSubtree	(2)
	 *		},
	 *		derefAliases	ENUMERATED {
	 *			neverDerefaliases	(0),
	 *			derefInSearching	(1),
	 *			derefFindingBaseObj	(2),
	 *			alwaysDerefAliases	(3)
	 *		},
	 *		sizelimit	INTEGER (0 .. 65535),
	 *		timelimit	INTEGER (0 .. 65535),
	 *		attrsOnly	BOOLEAN,
	 *		filter		Filter,
	 *		attributes	SEQUENCE OF AttributeType
	 *	}
	 * wrapped in an ldap message.
	 */

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( NULL );
	}

	if ( base == NULL ) {
		/* no base provided, use session default base */
		base = ld->ld_options.ldo_defbase;

		if ( base == NULL ) {
			/* no session default base, use top */
			base = "";
		}
	}

#ifdef LDAP_CONNECTIONLESS
	if ( LDAP_IS_UDP(ld) ) {
	    err = ber_write( ber, ld->ld_options.ldo_peer,
		    sizeof(struct sockaddr), 0);
	}
	if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) {
	    char *dn = ld->ld_options.ldo_cldapdn;
	    if (!dn) dn = "";
	    err = ber_printf( ber, "{ist{seeiib", ++ld->ld_msgid, dn,
		LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
		(sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
		(timelimit < 0) ? ld->ld_timelimit : timelimit,
		attrsonly );
	} else
#endif
	{
	    err = ber_printf( ber, "{it{seeiib", ++ld->ld_msgid,
		LDAP_REQ_SEARCH, base, (ber_int_t) scope, ld->ld_deref,
		(sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
		(timelimit < 0) ? ld->ld_timelimit : timelimit,
		attrsonly );
	}

	if ( err == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	if( filter == NULL ) {
		filter = "(objectclass=*)";
	}

	err = ldap_pvt_put_filter( ber, filter );

	if ( err  == -1 ) {
		ld->ld_errno = LDAP_FILTER_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return( NULL );
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( NULL );
	}

	return( ber );
}
Exemple #7
0
int
ldap_rename(
	LDAP *ld,
	LDAP_CONST char *dn,
	LDAP_CONST char *newrdn,
	LDAP_CONST char *newSuperior,
	int deleteoldrdn,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	int *msgidp )
{
	BerElement	*ber;
	int rc;
	ber_int_t id;

	Debug( LDAP_DEBUG_TRACE, "ldap_rename\n", 0, 0, 0 );

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( LDAP_NO_MEMORY );
	}

	LDAP_NEXT_MSGID( ld, id );
	if( newSuperior != NULL ) {
		/* must be version 3 (or greater) */
		if ( ld->ld_version < LDAP_VERSION3 ) {
			ld->ld_errno = LDAP_NOT_SUPPORTED;
			ber_free( ber, 1 );
			return( ld->ld_errno );
		}
		rc = ber_printf( ber, "{it{ssbtsN}", /* '}' */ 
			id, LDAP_REQ_MODDN,
			dn, newrdn, (ber_int_t) deleteoldrdn,
			LDAP_TAG_NEWSUPERIOR, newSuperior );

	} else {
		rc = ber_printf( ber, "{it{ssbN}", /* '}' */ 
			id, LDAP_REQ_MODDN,
			dn, newrdn, (ber_int_t) deleteoldrdn );
	}

	if ( rc < 0 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	rc = ber_printf( ber, /*{*/ "N}" );
	if ( rc < 0 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODRDN, dn, ber, id );
	
	if( *msgidp < 0 ) {
		return( ld->ld_errno );
	}

	return LDAP_SUCCESS;
}
Exemple #8
0
int
ldap_verify_credentials(LDAP *ld,
	struct berval	*cookie,
	LDAP_CONST char *dn,
	LDAP_CONST char *mechanism,
	struct berval	*cred,
    LDAPControl		**vcctrls,
	LDAPControl		**sctrls,
	LDAPControl		**cctrls,
	int				*msgidp)
{
	int rc;
	BerElement *ber;
	struct berval reqdata;

	assert(ld != NULL);
	assert(LDAP_VALID(ld));
	assert(msgidp != NULL);

	ber = ber_alloc_t(LBER_USE_DER);
	if (dn == NULL) dn = "";

	if (mechanism == LDAP_SASL_SIMPLE) {
		assert(!cookie);

		rc = ber_printf(ber, "{stO" /*"}"*/,
			dn, LDAP_AUTH_SIMPLE, cred);

	} else {
		if (!cred || BER_BVISNULL(cred)) {
			if (cookie) {
				rc = ber_printf(ber, "{tOst{sN}" /*"}"*/,
					LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, cookie,
					dn, LDAP_AUTH_SASL, mechanism);
			} else {
				rc = ber_printf(ber, "{st{sN}N" /*"}"*/,
					dn, LDAP_AUTH_SASL, mechanism);
			}
		} else {
			if (cookie) {
				rc = ber_printf(ber, "{tOst{sON}" /*"}"*/,
					LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, cookie,
					dn, LDAP_AUTH_SASL, mechanism, cred);
			} else {
				rc = ber_printf(ber, "{st{sON}" /*"}"*/,
					dn, LDAP_AUTH_SASL, mechanism, cred);
			}
		}
	}

	if (rc < 0) {
		rc = ld->ld_errno = LDAP_ENCODING_ERROR;
		goto done;
	}

	if (vcctrls && *vcctrls) {
		LDAPControl *const *c;

		rc = ber_printf(ber, "t{" /*"}"*/, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS);

		for (c=vcctrls; *c; c++) {
			rc = ldap_pvt_put_control(*c, ber);
			if (rc != LDAP_SUCCESS) {
				rc = ld->ld_errno = LDAP_ENCODING_ERROR;
				goto done;
			}
		}

		rc = ber_printf(ber, /*"{{"*/ "}N}");

	} else {
		rc = ber_printf(ber, /*"{"*/ "N}");
	}

	if (rc < 0) {
		rc = ld->ld_errno = LDAP_ENCODING_ERROR;
		goto done;
	}


	rc = ber_flatten2(ber, &reqdata, 0);
	if (rc < 0) {
		rc = ld->ld_errno = LDAP_ENCODING_ERROR;
		goto done;
	}

	rc = ldap_extended_operation(ld, LDAP_EXOP_VERIFY_CREDENTIALS,
		&reqdata, sctrls, cctrls, msgidp);

done:
	ber_free(ber, 1);
	return rc;
}
Exemple #9
0
static int
do_abandon(
	LDAP *ld,
	ber_int_t origid,
	ber_int_t msgid,
	LDAPControl **sctrls,
	int sendabandon )
{
	BerElement	*ber;
	int		i, err;
	Sockbuf		*sb;
	LDAPRequest	*lr;

	Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n",
		origid, msgid, 0 );

	/* find the request that we are abandoning */
start_again:;
	lr = ld->ld_requests;
	while ( lr != NULL ) {
		/* this message */
		if ( lr->lr_msgid == msgid ) {
			break;
		}

		/* child: abandon it */
		if ( lr->lr_origid == msgid && !lr->lr_abandoned ) {
			(void)do_abandon( ld, lr->lr_origid, lr->lr_msgid,
				sctrls, sendabandon );

			/* restart, as lr may now be dangling... */
			goto start_again;
		}

		lr = lr->lr_next;
	}

	if ( lr != NULL ) {
		if ( origid == msgid && lr->lr_parent != NULL ) {
			/* don't let caller abandon child requests! */
			ld->ld_errno = LDAP_PARAM_ERROR;
			return( LDAP_PARAM_ERROR );
		}
		if ( lr->lr_status != LDAP_REQST_INPROGRESS ) {
			/* no need to send abandon message */
			sendabandon = 0;
		}
	}

	/* ldap_msgdelete locks the res_mutex. Give up the req_mutex
	 * while we're in there.
	 */
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
#endif
	err = ldap_msgdelete( ld, msgid );
#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
	if ( err == 0 ) {
		ld->ld_errno = LDAP_SUCCESS;
		return LDAP_SUCCESS;
	}

	/* fetch again the request that we are abandoning */
	if ( lr != NULL ) {
		for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) {
			/* this message */
			if ( lr->lr_msgid == msgid ) {
				break;
			}
		}
	}

	err = 0;
	if ( sendabandon ) {
		if ( ber_sockbuf_ctrl( ld->ld_sb, LBER_SB_OPT_GET_FD, NULL ) == -1 ) {
			/* not connected */
			err = -1;
			ld->ld_errno = LDAP_SERVER_DOWN;

		} else if ( ( ber = ldap_alloc_ber_with_options( ld ) ) == NULL ) {
			/* BER element allocation failed */
			err = -1;
			ld->ld_errno = LDAP_NO_MEMORY;

		} else {
			/*
			 * We already have the mutex in LDAP_R_COMPILE, so
			 * don't try to get it again.
			 *		LDAP_NEXT_MSGID(ld, i);
			 */

			i = ++(ld)->ld_msgid;
#ifdef LDAP_CONNECTIONLESS
			if ( LDAP_IS_UDP(ld) ) {
				struct sockaddr sa = {0};
				/* dummy, filled with ldo_peer in request.c */
				err = ber_write( ber, &sa, sizeof(sa), 0 );
			}
			if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version ==
				LDAP_VERSION2 )
			{
				char *dn = ld->ld_options.ldo_cldapdn;
				if (!dn) dn = "";
				err = ber_printf( ber, "{isti",  /* '}' */
					i, dn,
					LDAP_REQ_ABANDON, msgid );
			} else
#endif
			{
				/* create a message to send */
				err = ber_printf( ber, "{iti",  /* '}' */
					i,
					LDAP_REQ_ABANDON, msgid );
			}

			if ( err == -1 ) {
				/* encoding error */
				ld->ld_errno = LDAP_ENCODING_ERROR;

			} else {
				/* Put Server Controls */
				if ( ldap_int_put_controls( ld, sctrls, ber )
					!= LDAP_SUCCESS )
				{
					err = -1;

				} else {
					/* close '{' */
					err = ber_printf( ber, /*{*/ "N}" );

					if ( err == -1 ) {
						/* encoding error */
						ld->ld_errno = LDAP_ENCODING_ERROR;
					}
				}
			}

			if ( err == -1 ) {
				ber_free( ber, 1 );

			} else {
				/* send the message */
				if ( lr != NULL ) {
					assert( lr->lr_conn != NULL );
					sb = lr->lr_conn->lconn_sb;
				} else {
					sb = ld->ld_sb;
				}

				if ( ber_flush2( sb, ber, LBER_FLUSH_FREE_ALWAYS ) != 0 ) {
					ld->ld_errno = LDAP_SERVER_DOWN;
					err = -1;
				} else {
					err = 0;
				}
			}
		}
	}

	if ( lr != NULL ) {
		if ( sendabandon || lr->lr_status == LDAP_REQST_WRITING ) {
			ldap_free_connection( ld, lr->lr_conn, 0, 1 );
		}

		if ( origid == msgid ) {
			ldap_free_request( ld, lr );

		} else {
			lr->lr_abandoned = 1;
		}
	}

#ifdef LDAP_R_COMPILE
	/* ld_abandoned is actually protected by the ld_res_mutex;
	 * give up the ld_req_mutex and get the other */
	ldap_pvt_thread_mutex_unlock( &ld->ld_req_mutex );
	ldap_pvt_thread_mutex_lock( &ld->ld_res_mutex );
#endif

	/* use bisection */
	i = 0;
	if ( ld->ld_nabandoned == 0 ||
		ldap_int_bisect_find( ld->ld_abandoned, ld->ld_nabandoned, msgid, &i ) == 0 )
	{
		ldap_int_bisect_insert( &ld->ld_abandoned, &ld->ld_nabandoned, msgid, i );
	}

	if ( err != -1 ) {
		ld->ld_errno = LDAP_SUCCESS;
	}

#ifdef LDAP_R_COMPILE
	ldap_pvt_thread_mutex_unlock( &ld->ld_res_mutex );
	ldap_pvt_thread_mutex_lock( &ld->ld_req_mutex );
#endif
	return( ld->ld_errno );
}
Exemple #10
0
static
int
WriteMetaDataAttribute(
   VDIR_OPERATION *             op,
   VDIR_ATTRIBUTE *             pAttr,
   int                          numAttrMetaData,
   PATTRIBUTE_META_DATA_NODE    pAttrMetaData,
   BerElement *                 ber,
   BOOLEAN *                    nonTrivialAttrsInReplScope,
   PSTR*                        ppszErrorMsg
   )
{
    int             retVal = LDAP_SUCCESS;
    VDIR_BERVALUE   attrMetaData = { {ATTR_ATTR_META_DATA_LEN, ATTR_ATTR_META_DATA}, 0, 0, NULL };
    int             i = 0;
    VDIR_BERVALUE   berVal = VDIR_BERVALUE_INIT;
    char            attrMetaDataVal[256 + VMDIR_MAX_ATTR_META_DATA_LEN];
    PSTR            pszLocalErrorMsg = NULL;

    *nonTrivialAttrsInReplScope = FALSE;

    if (ber_printf( ber, "{O[", &(attrMetaData) ) == -1 )
    {
        VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: ber_printf (to print attribute name ...) failed" );
        retVal = LDAP_OTHER;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Encoding attribute type failed.");
    }

    for ( ; pAttr != NULL; pAttr = pAttr->next)
    {
        // By this time, we have already filtered out attributes that should be send back to replication consumer
        // in prior WriteAttributes -> IsAttrInReplScope call.  They contain proper pAttr->metaData value.
        if (pAttr->metaData[0] != '\0')
        {
            VmDirStringPrintFA( attrMetaDataVal, sizeof(attrMetaDataVal), "%.256s:%s", pAttr->type.lberbv.bv_val, pAttr->metaData);
            berVal.lberbv.bv_val = attrMetaDataVal;
            berVal.lberbv.bv_len = VmDirStringLenA( attrMetaDataVal );
            if (VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_MODIFYTIMESTAMP, FALSE ) != 0 &&
                VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_USN_CHANGED, FALSE ) != 0)
            {
                // To prevent endless replication ping pong, supplier should send result only if there are changes
                // to attribute other than ATTR_USN_CHANGED and ATTR_MODIFYTIMESTAMP.
                *nonTrivialAttrsInReplScope = TRUE;
            }
            if (ber_printf( ber, "O", &berVal ) == -1 )
            {
                VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: ber_printf (to print an attribute value ...) failed." );
                retVal = LDAP_OTHER;
                BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                "Encoding an attribute value failed.");
            }
        }
    }
    // include attrMetaData for the deleted attributes
    for (i = 0; i<numAttrMetaData; i++)
    {
        if (pAttrMetaData[i].metaData[0] != '\0')
        {
            BOOLEAN                 bSendAttrMetaData = TRUE;
            PVDIR_SCHEMA_AT_DESC    pATDesc = NULL;

            if (op->syncReqCtrl != NULL) // Replication
            {
                retVal = IsAttrInReplScope( op, NULL, pAttrMetaData[i].metaData, &bSendAttrMetaData, &pszLocalErrorMsg );
                BAIL_ON_VMDIR_ERROR( retVal );
            }
            else
            {
                bSendAttrMetaData = TRUE;
            }
            if (bSendAttrMetaData)
            {
                if ((pATDesc = VmDirSchemaAttrIdToDesc(op->pSchemaCtx, pAttrMetaData[i].attrID)) == NULL)
                {
                    VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL,
                              "WriteMetaDataAttribute: VmDirSchemaAttrIdToDesc failed for attribute id: %d.",
                              pAttrMetaData[i].attrID  );
                    retVal = LDAP_OTHER;
                    BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                    "WriteMetaDataAttribute: VmDirSchemaAttrIdToDesc failed.");
                }
                VmDirStringPrintFA( attrMetaDataVal, sizeof(attrMetaDataVal), "%.256s:%s", pATDesc->pszName, pAttrMetaData[i].metaData);
                berVal.lberbv.bv_val = attrMetaDataVal;
                berVal.lberbv.bv_len = VmDirStringLenA( attrMetaDataVal );
                *nonTrivialAttrsInReplScope = TRUE;
                if (ber_printf( ber, "O", &berVal ) == -1 )
                {
                    VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: ber_printf (to print an attribute value ...) failed." );
                    retVal = LDAP_OTHER;
                    BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                    "Encoding an attribute value failed.");
                }
            }
        }
    }

    if ( ber_printf( ber, "]N}" ) == -1 )
    {
        VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: ber_printf (to terminate an attribute's values ...) failed" );
        retVal = LDAP_OTHER;
        BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                        "Encoding terminating an attribute type failed.");
    }

cleanup:

    if (ppszErrorMsg)
    {
        *ppszErrorMsg = pszLocalErrorMsg;
    }
    else
    {
        VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    }

    return( retVal );

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute failed (%u)(%s)",
                     retVal, VDIR_SAFE_STRING(pszLocalErrorMsg) );
    goto cleanup;
}
Exemple #11
0
int
ldap_sasl_bind(
	LDAP			*ld,
	LDAP_CONST char	*dn,
	LDAP_CONST char	*mechanism,
	struct berval	*cred,
	LDAPControl		**sctrls,
	LDAPControl		**cctrls,
	int				*msgidp )
{
	BerElement	*ber;
	int rc;

#ifdef NEW_LOGGING
	LDAP_LOG ( TRANSPORT, ENTRY, "ldap_sasl_bind\n", 0, 0, 0 );
#else
	Debug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 );
#endif

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( msgidp != NULL );

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	if( mechanism == LDAP_SASL_SIMPLE ) {
		if( dn == NULL && cred != NULL && cred->bv_len ) {
			/* use default binddn */
			dn = ld->ld_defbinddn;
		}

	} else if( ld->ld_version < LDAP_VERSION3 ) {
		ld->ld_errno = LDAP_NOT_SUPPORTED;
		return ld->ld_errno;
	}

	if ( dn == NULL ) {
		dn = "";
	}

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	assert( LBER_VALID( ber ) );

	if( mechanism == LDAP_SASL_SIMPLE ) {
		/* simple bind */
		rc = ber_printf( ber, "{it{istON}" /*}*/,
			++ld->ld_msgid, LDAP_REQ_BIND,
			ld->ld_version, dn, LDAP_AUTH_SIMPLE,
			cred );
		
	} else if ( cred == NULL || cred->bv_val == NULL ) {
		/* SASL bind w/o creditials */
		rc = ber_printf( ber, "{it{ist{sN}N}" /*}*/,
			++ld->ld_msgid, LDAP_REQ_BIND,
			ld->ld_version, dn, LDAP_AUTH_SASL,
			mechanism );

	} else {
		/* SASL bind w/ creditials */
		rc = ber_printf( ber, "{it{ist{sON}N}" /*}*/,
			++ld->ld_msgid, LDAP_REQ_BIND,
			ld->ld_version, dn, LDAP_AUTH_SASL,
			mechanism, cred );
	}

	if( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( -1 );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return ld->ld_errno;
	}


	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_BIND, dn, ber );

	if(*msgidp < 0)
		return ld->ld_errno;

	return LDAP_SUCCESS;
}
Exemple #12
0
static
int
WriteAttributes(
   VDIR_OPERATION *   op,
   PVDIR_ENTRY        pEntry,
   uint32_t           iSearchReqSpecialChars,
   BerElement *       ber,
   PSTR*              ppszErrorMsg
   )
{
    int             retVal = LDAP_SUCCESS;
    unsigned int    i = 0;
    SearchReq *     sr = &(op->request.searchReq);
    BOOLEAN         mapFSPDN = FALSE;
    PVDIR_ATTRIBUTE pAttr = NULL;
    PVDIR_ATTRIBUTE pRetAttrs[3] = {pEntry->attrs, pEntry->pComputedAttrs, NULL};
    DWORD           dwCnt = 0;
    PSTR            pszLocalErrorMsg = NULL;

    // loop through both normal and computed attributes
    for ( dwCnt = 0, pAttr = pRetAttrs[dwCnt];
          pAttr != NULL;
          ++dwCnt, pAttr = pRetAttrs[dwCnt])
    {
        for ( ; pAttr != NULL;  pAttr = pAttr->next )
        {
            BOOLEAN bSendAttribute = FALSE;

            if (op->syncReqCtrl != NULL) // Replication,
            {
                // Filter attributes based on the input utdVector, and attribute's meta-data
                retVal = IsAttrInReplScope( op, pAttr->type.lberbv.bv_val, pAttr->metaData, &bSendAttribute, &pszLocalErrorMsg );
                BAIL_ON_VMDIR_ERROR( retVal );
            }
            else
            {
                // WEI: the correct way to handle this is to have attribute level 'ACL' check
                // For instance, the 'userPassword' attribute ACL defines:
                // Deny 'READ' access to everyone including administrator/admins/SELF
                // Possibly only allow 'backup Operators' 'READ' access
                // Allow 'administrator/admins' WRITE (set password)
                // Allow 'SELF' WRITE (reset password)

                // For now, do not send 'userPassword' attribute for everyone when implicitly/explicitly requested

                // normal ldap client search request
                // check if we need to return this attribute

                if (VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_USER_PASSWORD, FALSE) == 0)
                {
                    if ((iSearchReqSpecialChars & LDAP_SEARCH_REQUEST_CHAR_PASSWD) != 0)
                    {   // vmdir specific - return password only if special char '-' is requested
                        bSendAttribute = TRUE;
                    }
                }
                else if (VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_KRB_MASTER_KEY, FALSE) == 0)
                {
                    //only return master key if all of following conditions are satisfied
                    if (op->showMasterKeyCtrl && // server control must be present
                            op->conn->bIsLdaps && // must be ldaps
                            op->conn->AccessInfo.pszNormBindedDn && // can't be anonymous
                            VmDirStringCompareA(op->reqDn.bvnorm_val, gVmdirServerGlobals.systemDomainDN.bvnorm_val, FALSE) == 0 && // must query system domain object
                            op->request.searchReq.scope == LDAP_SCOPE_BASE && // scope must be base
                            op->request.searchReq.attrs != NULL && // attribute must be krbMKey only
                            VmDirStringCompareA(op->request.searchReq.attrs[0].lberbv.bv_val, ATTR_KRB_MASTER_KEY, FALSE) == 0 &&
                            op->request.searchReq.attrs[1].lberbv.bv_val == NULL)
                    {
                        retVal = VmDirSrvAccessCheckIsAdminRole( //must be administrator
                                                        op,
                                                        op->conn->AccessInfo.pszNormBindedDn,
                                                        &op->conn->AccessInfo,
                                                        &bSendAttribute);
                        BAIL_ON_VMDIR_ERROR( retVal );
                    }
                }
                else if ( (VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_VMW_STS_PASSWORD, FALSE) == 0)
                           ||
                           (VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_VMW_STS_TENANT_KEY, FALSE) == 0)
                        )
                {
                    //only admin users can read ATTR_VMW_STS_PASSWORD, ATTR_VMW_STS_TENANT_KEY attribute
                    {
                        retVal = VmDirSrvAccessCheckIsAdminRole( //must be administrator
                                                        op,
                                                        op->conn->AccessInfo.pszNormBindedDn,
                                                        &op->conn->AccessInfo,
                                                        &bSendAttribute);
                        BAIL_ON_VMDIR_ERROR( retVal );
                    }
                }
                else if (((iSearchReqSpecialChars & LDAP_SEARCH_REQUEST_CHAR_USER) != 0)                   &&
                         pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_USER_APPLICATIONS)
                {
                    bSendAttribute = TRUE;   // return all user attributes - "*"
                }
                else if (((iSearchReqSpecialChars & LDAP_SEARCH_REQUEST_CHAR_OP) != 0)                     &&
                         (pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_DIRECTORY_OPERATION ||
                          pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_DSA_OPERATION       ||
                          pAttr->pATDesc->usage == VDIR_ATTRIBUTETYPE_DISTRIBUTED_OPERATION))
                {
                    bSendAttribute = TRUE;   // return all operational attributes - "+"
                }
                else
                {
                    for (i = 0; sr->attrs && sr->attrs[i].lberbv.bv_val != NULL; i++)
                    {
                        if (VmDirStringCompareA( sr->attrs[i].lberbv.bv_val, pAttr->type.lberbv.bv_val, FALSE) == 0)
                        {
                           bSendAttribute = TRUE;
                           break;
                        }
                    }
                }
            }

            if (bSendAttribute)
            {
                if (ber_printf( ber, "{O[", &(pAttr->type) ) == -1 )
                {
                    VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to print attribute name ...) failed" );
                    retVal = LDAP_OTHER;
                    BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                    "Encoding attribute type failed.");
                }

                // Non-replication/normal search request, and the attribute is FSP enabled (SJ-TBD, for now ATTR_MEMBER)
                if (op->syncReqCtrl == NULL && VmDirStringCompareA(pAttr->type.lberbv.bv_val, ATTR_MEMBER, FALSE) == 0)
                {
                    mapFSPDN = TRUE;
                }
                else
                {
                    mapFSPDN = FALSE;
                }

                if ( VmDirStringCompareA( pAttr->type.lberbv_val, ATTR_OBJECT_CLASS, FALSE ) == 0 )
                {
                    if ( op->syncReqCtrl == NULL ) // Not replication
                    {
                        BerValue bvOCTop = {OC_TOP_LEN, OC_TOP};
                        // explicitly send TOP as we don't store it in Entry/DB
                        if (ber_printf( ber, "O", &bvOCTop ) == -1 )
                        {
                            VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to print an attribute value ...) failed." );
                            retVal = LDAP_OTHER;
                            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                            "Encoding an attribute value failed.");
                        }
                    }

                    // ADSI wants structure objetclass at the end to display correctly.
                    for ( i = pAttr->numVals ; i > 0; i-- )
                    {
                        if (ber_printf( ber, "O", &(pAttr->vals[i-1]) ) == -1 )
                        {
                            VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to print an attribute value ...) failed." );
                            retVal = LDAP_OTHER;
                            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                            "Encoding an attribute value failed.");
                        }
                    }
                }
                else
                {
                    for ( i = 0; i< pAttr->numVals; i++ )
                    {
                        // SJ-TBD: A better/bit-more-expensive way is to Normalize the value, do GetParentDN, check if the 1st
                        // RDN is FSP container RDN ...
                        if (mapFSPDN && VmDirStringStrA(pAttr->vals[i].lberbv.bv_val, FSP_CONTAINER_RDN_ATTR_VALUE) != NULL)
                        {
                            char * tmpPos = VmDirStringChrA(pAttr->vals[i].lberbv.bv_val, ',');
                            assert( tmpPos != NULL);
                            *tmpPos = '\0';
                            pAttr->vals[i].lberbv.bv_len = tmpPos - pAttr->vals[i].lberbv.bv_val;
                        }
                        if (ber_printf( ber, "O", &(pAttr->vals[i]) ) == -1 )
                        {
                            VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to print an attribute value ...) failed." );
                            retVal = LDAP_OTHER;
                            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                            "Encoding an attribute value failed.");
                        }
                    }
                }

                if ( ber_printf( ber, "]N}" ) == -1 )
                {
                    VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteAttributes: ber_printf (to terminate an attribute's values ...) failed" );
                    retVal = LDAP_OTHER;
                    BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                    "Encoding terminating an attribute type failed.");
                }
            }
        }
    }

cleanup:

    if (ppszErrorMsg)
    {
        *ppszErrorMsg = pszLocalErrorMsg;
    }
    else
    {
        VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);
    }

    return( retVal );

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WriteAttributes failed (%u)(%s)",
                     retVal, VDIR_SAFE_STRING(pszLocalErrorMsg) );

    goto cleanup;
}
Exemple #13
0
int
VmDirSendSearchEntry(
   PVDIR_OPERATION     pOperation,
   PVDIR_ENTRY         pSrEntry
   )
{
    int                         retVal = LDAP_SUCCESS;
    BerElementBuffer            berbuf;
    BerElement *                ber = (BerElement *) &berbuf;
    BOOLEAN                     bFreeBer = FALSE;
    ber_len_t                   iBlobSize = 0;
    BerValue                    lberBervEntryBlob = {0};
    int                         nAttrs = 0;
    int                         nVals = 0;
    BOOLEAN                     attrMetaDataReqd = FALSE;
    SearchReq *                 sr = &(pOperation->request.searchReq);
    int                         i = 0;
    BOOLEAN                     nonTrivialAttrsInReplScope = FALSE;
    uint32_t                    iSearchReqSpecialChars = 0;
    PATTRIBUTE_META_DATA_NODE   pAttrMetaData = NULL;
    int                         numAttrMetaData = 0;
    PVDIR_ATTRIBUTE             pAttr = NULL;
    USN                         usnChanged = 0;
    PSTR                        pszLocalErrorMsg = NULL;

    if ( !pOperation || !pSrEntry )
    {
        retVal = ERROR_INVALID_PARAMETER;
        BAIL_ON_VMDIR_ERROR(retVal);
    }

    pSrEntry->bSearchEntrySent = FALSE;

    // see if client request has "*" and/or "+" ("-" for userpassword internal to vmdir)
    // WEI TODO: when we have attribute level ACL check, this information will be useful
    // return result will depend on ACL each on each attribute client is asking before
    // generating a final result to send back
    SetSpecialReturnChar(&pOperation->request.searchReq, &iSearchReqSpecialChars);

    if ( pSrEntry->eId == DSE_ROOT_ENTRY_ID
         &&
         pOperation->request.searchReq.attrs == NULL
       )
    {
        //  For ADSI, if no specific attributes requested of DSE ROOT search,
        //  return ALL (include operational) attributes.
        iSearchReqSpecialChars |= LDAP_SEARCH_REQUEST_CHAR_OP;
    }

    // ACL check before processing/sending the current srEntry back
    retVal = VmDirSrvAccessCheck( pOperation, &pOperation->conn->AccessInfo, pSrEntry, VMDIR_RIGHT_DS_READ_PROP );
    BAIL_ON_VMDIR_ERROR( retVal );

    if ( pOperation->opType == VDIR_OPERATION_TYPE_INTERNAL )
    {
        ; // no op in INTERNAL case
    }
    else
    {
        // If not replication, and showDeletedObjectsCtrl not present, => don't send back Deleted objects (tombstones).
        if (pOperation->syncReqCtrl == NULL && pOperation->showDeletedObjectsCtrl == NULL)
        {
            pAttr = VmDirEntryFindAttribute(ATTR_IS_DELETED, pSrEntry);
            if (pAttr)
            {
                if (VmDirStringCompareA((PSTR)pAttr->vals[0].lberbv.bv_val, VMDIR_IS_DELETED_TRUE_STR, FALSE) == 0)
                {
                    goto cleanup; // Don't send this entry
                }
            }
        }
        // In case of replication request, skip certain updates
        if (pOperation->syncReqCtrl != NULL)
        {
            PVDIR_ATTRIBUTE                 pAttrUsnCreated = NULL;
            USN                             usnCreated = 0;
            USN                             limitUsn = 0;
            VMDIR_REPLICATION_AGREEMENT *   replAgr = NULL;

            pAttr = VmDirEntryFindAttribute(ATTR_USN_CHANGED, pSrEntry);
            assert( pAttr != NULL );
            usnChanged = VmDirStringToLA( pAttr->vals[0].lberbv.bv_val, NULL, 10);

            // Check if usnChanged is beyond successful replication update state
            limitUsn = VmDirdGetLimitLocalUsnToBeSupplied();
            if (limitUsn != 0 && usnChanged >= limitUsn)
            {
                VMDIR_LOG_INFO(VMDIR_LOG_MASK_ALL, "SendSearchEntry: bug# 863244 RACE CONDITION encountered., "
                          "usnChanged = %ld, limitLocalUsnToBeSupplied = %ld, skipping entry: %s", usnChanged,
                          limitUsn, pSrEntry->dn.lberbv.bv_val );
                goto cleanup; // Don't send this entry
            }

            // Check if usnChanged is beyond lowestPendingUncommittedUsn recorded at the beginning of replication search

            if (pOperation->lowestPendingUncommittedUsn != 0 && usnChanged >= pOperation->lowestPendingUncommittedUsn)
            {
                VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: usnChanged = %ld, lowestPendingUncommittedUsn = %ld, "
                          "skipping entry: %s", usnChanged, pOperation->lowestPendingUncommittedUsn,
                          pSrEntry->dn.lberbv.bv_val );
                goto cleanup; // Don't send this entry
            }

            // Don't send (skip) modifications to my server object, and my RAs
            pAttrUsnCreated = VmDirEntryFindAttribute(ATTR_USN_CREATED, pSrEntry);
            assert( pAttrUsnCreated != NULL );
            usnCreated = VmDirStringToLA( pAttrUsnCreated->vals[0].lberbv.bv_val, NULL, 10);
            // Only send back creation of certain objects, and not their modifications.
            // Check if consumer has already seen the creation. If yes, we are dealing with mods, which should be skipped
            // for my server object, and my RAs
            // Note: Skipping mods for RAs and Server Objects will cause inconsistencies with replicas. But these
            // two types only have local scope regarding functional effects. But if we are looking up / processing
            // information for these two types of objects on a replica, we need to watch out for potential
            // inconsistencies against the original source.
            if (pOperation->syncReqCtrl->value.syncReqCtrlVal.intLastLocalUsnProcessed > usnCreated)
            {
                if (strcmp(pSrEntry->dn.bvnorm_val, gVmdirServerGlobals.serverObjDN.bvnorm_val) == 0)
                {
                    VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Not sending modifications to my server object, DN: %s",
                              gVmdirServerGlobals.serverObjDN.lberbv.bv_val );
                    goto cleanup; // Don't send this entry
                }
                for (replAgr = gVmdirReplAgrs; replAgr != NULL; replAgr = replAgr->next )
                {
                    if (strcmp(pSrEntry->dn.bvnorm_val, replAgr->dn.bvnorm_val) == 0)
                    {
                        VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Not sending modifications to my RA object, DN: %s",
                                  replAgr->dn.bvnorm_val );
                        goto cleanup; // Don't send this entry
                    }
                }
            }

            // do not replicate DSE Root entry, because it is a "local" entry.
            if (pSrEntry->eId == DSE_ROOT_ENTRY_ID)
            {
                VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Not sending modifications to DSE Root entry, DN: %s",
                          pSrEntry->dn.bvnorm_val );
                goto cleanup; // Don't send this entry
            }

        }

        // Approximate calculation for the required ber size, because apart from lengths and strings, ber also includes
        // tags.
        if ( VmDirComputeEncodedEntrySize(pSrEntry, &nAttrs, &nVals, &iBlobSize) != 0
             ||
             VmDirAllocateMemory(iBlobSize, (PVOID*)&lberBervEntryBlob.bv_val) != 0
           )
        {
            retVal = LDAP_OPERATIONS_ERROR;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg), "no memory");
        }
        lberBervEntryBlob.bv_len = iBlobSize;

        ber_init2( ber, &lberBervEntryBlob, LBER_USE_DER );  // ber takes over lberBervEntryBlob.lberbv.bv_val ownership
        bFreeBer = TRUE;

        if ( ber_printf( ber, "{it{O{", pOperation->msgId, LDAP_RES_SEARCH_ENTRY, &pSrEntry->dn ) == -1)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry: ber_printf (to print msgId ...) failed" );
            retVal = LDAP_OTHER;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "Encoding msgId, RES_SEARCH_ENTRY, DN failed");
        }
        // Determine if we need to send back the attribute metaData
        if ( pOperation->syncReqCtrl != NULL ) // Replication
        {
            attrMetaDataReqd = TRUE;
        }
        else // check if attrMetaData attribute has been requested explicitly.
        {
            if (sr->attrs != NULL)
            {
                for (i = 0; sr->attrs[i].lberbv.bv_val != NULL; i++)
                {
                    if (VmDirStringCompareA( sr->attrs[i].lberbv.bv_val, ATTR_ATTR_META_DATA, FALSE) == 0)
                    {
                        attrMetaDataReqd = TRUE;
                        break;
                    }
                }
            }
        }

        if (attrMetaDataReqd)
        {
            if ((pOperation->pBEIF->pfnBEGetAllAttrsMetaData( pOperation->pBECtx, pSrEntry->eId, &pAttrMetaData,
                                                              &numAttrMetaData )) != 0)
            {
                VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry: pfnBEGetAllAttrsMetaData failed for entryId: %ld",
                                   pSrEntry->eId);
                retVal = LDAP_OPERATIONS_ERROR;
                BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                                "pfnBEGetAllAttrsMetaData failed.");
            }

            // SJ-TBD: Following double for loop to be optimized
            // Copy attrMetaData to corresponding attributes
            for (i=0; i<numAttrMetaData; i++)
            {
                for ( pAttr = pSrEntry->attrs; pAttr != NULL; pAttr = pAttr->next)
                {
                    if (pAttr->pATDesc->usAttrID == pAttrMetaData[i].attrID)
                    {
                        VmDirStringCpyA( pAttr->metaData, VMDIR_MAX_ATTR_META_DATA_LEN, pAttrMetaData[i].metaData );
                        pAttrMetaData[i].metaData[0] = '\0';
                    }
                }
            }
        }

        retVal = WriteAttributes( pOperation, pSrEntry, iSearchReqSpecialChars , ber, &pszLocalErrorMsg );
        BAIL_ON_VMDIR_ERROR( retVal );

        if (attrMetaDataReqd)
        {
            retVal = WriteMetaDataAttribute( pOperation, pSrEntry->attrs, numAttrMetaData, pAttrMetaData, ber,
                                             &nonTrivialAttrsInReplScope, &pszLocalErrorMsg );
            BAIL_ON_VMDIR_ERROR( retVal );
        }

        if (ber_printf( ber, "N}N}" ) == -1)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                      "ber_printf (to terminate the entry and the complete search result entry message ...) failed" );
            retVal = LDAP_OTHER;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "Encoding terminating the entry failed.");
        }

        if ( pOperation->syncReqCtrl != NULL ) // Replication, => write Sync State Control
        {
            retVal = WriteSyncStateControl( pOperation, pSrEntry->attrs, ber, &pszLocalErrorMsg );
            BAIL_ON_VMDIR_ERROR( retVal );
        }

        if (ber_printf( ber, "N}" ) == -1)
        {
            VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                      "ber_printf (to terminate the entry and the complete search result entry message ...) failed" );;
            retVal = LDAP_OTHER;
            BAIL_ON_VMDIR_ERROR_WITH_MSG(   retVal, (pszLocalErrorMsg),
                                            "Encoding terminating the entry failed.");
        }

        if ((pOperation->syncReqCtrl == NULL) || (pOperation->syncReqCtrl != NULL && nonTrivialAttrsInReplScope ))
        {
            if (WriteBerOnSocket( pOperation->conn, ber ) != 0)
            {
                VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendSearchEntry: WriteBerOnSocket failed." );
                retVal = LDAP_UNAVAILABLE;
                BAIL_ON_VMDIR_ERROR( retVal );
            }

            pSrEntry->bSearchEntrySent = TRUE;
            sr->iNumEntrySent++;

            VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: Send entry: %s", pSrEntry->dn.lberbv.bv_val);
        }
        else
        {
            VMDIR_LOG_INFO( LDAP_DEBUG_REPL, "SendSearchEntry: NOT Sending entry: %s %p %d",
                            pSrEntry->dn.lberbv.bv_val, pOperation->syncReqCtrl, nonTrivialAttrsInReplScope);
        }

        // record max local usnChanged in syncControlDone
        if (pOperation->syncReqCtrl != NULL)
        {
            if (usnChanged  > pOperation->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed)
            {
                pOperation->syncDoneCtrl->value.syncDoneCtrlVal.intLastLocalUsnProcessed = usnChanged;
            }
        }

        retVal = LDAP_SUCCESS;
    }

cleanup:
    if (bFreeBer)
    {
        ber_free_buf( ber );
    }
    VMDIR_SAFE_FREE_MEMORY( pAttrMetaData );
    VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg);

    return( retVal );

error:

    VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL,
                     "SendSearchEntry failed DN=(%s), (%u)(%s)",
                     (pSrEntry && pSrEntry->dn.lberbv.bv_val) ? pSrEntry->dn.lberbv.bv_val : "",
                     retVal, VDIR_SAFE_STRING( pszLocalErrorMsg));

    if ( !pOperation->ldapResult.pszErrMsg && pszLocalErrorMsg )
    {
        pOperation->ldapResult.pszErrMsg = pszLocalErrorMsg;
        pszLocalErrorMsg = NULL;
    }

    goto cleanup;
}
Exemple #14
0
void
VmDirSendLdapResult(
   VDIR_OPERATION * op
   )
{
   BerElementBuffer berbuf;
   BerElement *     ber = (BerElement *) &berbuf;
   ber_int_t        msgId = 0;
   ber_tag_t        resCode = 0;
   size_t           iNumSearchEntrySent = 0;
   PCSTR            pszSocketInfo = NULL;

   (void) memset( (char *)&berbuf, '\0', sizeof( BerElementBuffer ));

   resCode = GetResultTag( op->reqCode );
   msgId = (resCode != LBER_SEQUENCE) ? op->msgId : 0;

   if ( resCode == LDAP_RES_SEARCH_RESULT )
   {
       iNumSearchEntrySent = op->request.searchReq.iNumEntrySent;
   }

   ber_init2( ber, NULL, LBER_USE_DER );

   if (op->conn)
   {
      pszSocketInfo = op->conn->szClientIP;
   }

   if (op->ldapResult.errCode &&
       op->ldapResult.errCode != LDAP_SASL_BIND_IN_PROGRESS)
   {
       VMDIR_LOG_ERROR(
          VMDIR_LOG_MASK_ALL,
          "VmDirSendLdapResult: Request (%d), Error (%d), Message (%s), (%u) socket (%s)",
          op->reqCode,
          op->ldapResult.errCode,
          VDIR_SAFE_STRING(op->ldapResult.pszErrMsg),
          iNumSearchEntrySent,
          VDIR_SAFE_STRING(pszSocketInfo));
   }
   else if ( op->reqCode == LDAP_REQ_SEARCH )
   {
       VMDIR_LOG_INFO(
          LDAP_DEBUG_ARGS,
          "VmDirSendLdapResult: Request (%d), Error (%d), Message (%s), (%u) socket (%s)",
          op->reqCode,
          op->ldapResult.errCode,
          VDIR_SAFE_STRING(op->ldapResult.pszErrMsg),
          iNumSearchEntrySent,
          VDIR_SAFE_STRING(pszSocketInfo));
   }

   if (ber_printf( ber, "{it{essN}", msgId, resCode, op->ldapResult.errCode, "",
                       VDIR_SAFE_STRING(op->ldapResult.pszErrMsg)) == -1)
   {
      VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print msgId ...) failed" );
      goto done;
   }

   // If Search, Replication, and one or more entries were sent back => Send back Sync Done Control
   if ( op->reqCode == LDAP_REQ_SEARCH && op->syncReqCtrl != NULL && op->syncDoneCtrl != NULL)
   {
       if (WriteSyncDoneControl( op, ber ) != LDAP_SUCCESS)
       {
           goto done;
       }
   }

   if ( op->reqCode == LDAP_REQ_SEARCH && op->showPagedResultsCtrl != NULL)
   {
       if (WritePagedSearchDoneControl( op, ber ) != LDAP_SUCCESS)
       {
           goto done;
       }
   }

   if (ber_printf( ber, "N}" ) == -1)
   {
      VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: ber_printf (to print msgId ...) failed" );
      goto done;
   }

   if (WriteBerOnSocket( op->conn, ber ) != 0)
   {
      VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "SendLdapResult: WriteBerOnSocket failed" );
      goto done;
   }

done:
   ber_free_buf( ber );

}
Exemple #15
0
int
VmDirCreateSyncRequestControl(
    PCSTR pszInvocationId,
    USN lastLocalUsnProcessed,
    PCSTR pszUtdVector,
    LDAPControl *           syncReqCtrl
    )
{
    int                 retVal = LDAP_SUCCESS;
    BerElement *        ber = NULL;
    PSTR                pszLastLocalUsnProcessed = NULL;

    if (syncReqCtrl == NULL)
    {
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
    }

    if ((ber = ber_alloc()) == NULL)
    {
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
    }

    if (VmDirAllocateStringPrintf(&pszLastLocalUsnProcessed, "%lld", lastLocalUsnProcessed))
    {
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
    }

    if ( ber_printf( ber, "{i{sss}}", LDAP_SYNC_REFRESH_ONLY,
                    pszInvocationId,
                    pszLastLocalUsnProcessed,
                    pszUtdVector ) == -1)
    {
        VMDIR_LOG_ERROR(VMDIR_LOG_MASK_ALL, "VmDirCreateSyncRequestControl: ber_printf failed." );
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_SIMPLE_LDAP_ERROR( retVal );
    }

    memset( syncReqCtrl, 0, sizeof( LDAPControl ));
    syncReqCtrl->ldctl_oid = LDAP_CONTROL_SYNC;
    syncReqCtrl->ldctl_iscritical = '1';
    if (ber_flatten2(ber, &syncReqCtrl->ldctl_value, 1))
    {
        retVal = LDAP_OPERATIONS_ERROR;
        BAIL_ON_SIMPLE_LDAP_ERROR(retVal);
    }

cleanup:
    VMDIR_SAFE_FREE_STRINGA(pszLastLocalUsnProcessed);
    if (ber)
    {
        ber_free(ber, 1);
    }
    return retVal;

ldaperror:
    ber_bvfree(&syncReqCtrl->ldctl_value);
    goto cleanup;
}
Exemple #16
0
BerElement *
ldap_build_search_req(
    LDAP *ld,
    LDAP_CONST char *base,
    ber_int_t scope,
    LDAP_CONST char *filter,
    char **attrs,
    ber_int_t attrsonly,
    LDAPControl **sctrls,
    LDAPControl **cctrls,
    ber_int_t timelimit,
    ber_int_t sizelimit,
    ber_int_t deref,
    ber_int_t *idp)
{
    BerElement	*ber;
    int		err;

    /*
     * Create the search request.  It looks like this:
     *	SearchRequest := [APPLICATION 3] SEQUENCE {
     *		baseObject	DistinguishedName,
     *		scope		ENUMERATED {
     *			baseObject	(0),
     *			singleLevel	(1),
     *			wholeSubtree	(2)
     *		},
     *		derefAliases	ENUMERATED {
     *			neverDerefaliases	(0),
     *			derefInSearching	(1),
     *			derefFindingBaseObj	(2),
     *			alwaysDerefAliases	(3)
     *		},
     *		sizelimit	INTEGER (0 .. 65535),
     *		timelimit	INTEGER (0 .. 65535),
     *		attrsOnly	BOOLEAN,
     *		filter		Filter,
     *		attributes	SEQUENCE OF AttributeType
     *	}
     * wrapped in an ldap message.
     */

    /* create a message to send */
    if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
        return( NULL );
    }

    if ( base == NULL ) {
        /* no base provided, use session default base */
        base = ld->ld_options.ldo_defbase;

        if ( base == NULL ) {
            /* no session default base, use top */
            base = "";
        }
    }

    LDAP_NEXT_MSGID( ld, *idp );
#ifdef LDAP_CONNECTIONLESS
    if ( LDAP_IS_UDP(ld) ) {
        struct sockaddr sa = {0};
        /* dummy, filled with ldo_peer in request.c */
        err = ber_write( ber, &sa, sizeof( sa ), 0 );
    }
    if ( LDAP_IS_UDP(ld) && ld->ld_options.ldo_version == LDAP_VERSION2) {
        char *dn = ld->ld_options.ldo_cldapdn;
        if (!dn) dn = "";
        err = ber_printf( ber, "{ist{seeiib", *idp, dn,
                          LDAP_REQ_SEARCH, base, (ber_int_t) scope,
                          (deref < 0) ? ld->ld_deref : deref,
                          (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
                          (timelimit < 0) ? ld->ld_timelimit : timelimit,
                          attrsonly );
    } else
#endif
    {
        err = ber_printf( ber, "{it{seeiib", *idp,
                          LDAP_REQ_SEARCH, base, (ber_int_t) scope,
                          (deref < 0) ? ld->ld_deref : deref,
                          (sizelimit < 0) ? ld->ld_sizelimit : sizelimit,
                          (timelimit < 0) ? ld->ld_timelimit : timelimit,
                          attrsonly );
    }

    if ( err == -1 ) {
        ld->ld_errno = LDAP_ENCODING_ERROR;
        ber_free( ber, 1 );
        return( NULL );
    }

    if( filter == NULL ) {
        filter = "(objectclass=*)";
    }

    err = ldap_pvt_put_filter( ber, filter );

    if ( err  == -1 ) {
        ld->ld_errno = LDAP_FILTER_ERROR;
        ber_free( ber, 1 );
        return( NULL );
    }

#ifdef LDAP_DEBUG
    if ( ldap_debug & LDAP_DEBUG_ARGS ) {
        char	buf[ BUFSIZ ], *ptr = " *";

        if ( attrs != NULL ) {
            int	i, len, rest = sizeof( buf );

            for ( i = 0; attrs[ i ] != NULL && rest > 0; i++ ) {
                ptr = &buf[ sizeof( buf ) - rest ];
                len = snprintf( ptr, rest, " %s", attrs[ i ] );
                rest -= (len >= 0 ? len : (int) sizeof( buf ));
            }

            if ( rest <= 0 ) {
                AC_MEMCPY( &buf[ sizeof( buf ) - STRLENOF( "...(truncated)" ) - 1 ],
                           "...(truncated)", STRLENOF( "...(truncated)" ) + 1 );
            }
            ptr = buf;
        }

        Debug( LDAP_DEBUG_ARGS, "ldap_build_search_req ATTRS:%s\n", ptr, 0,0 );
    }
#endif /* LDAP_DEBUG */

    if ( ber_printf( ber, /*{*/ "{v}N}", attrs ) == -1 ) {
        ld->ld_errno = LDAP_ENCODING_ERROR;
        ber_free( ber, 1 );
        return( NULL );
    }

    /* Put Server Controls */
    if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
        ber_free( ber, 1 );
        return( NULL );
    }

    if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
        ld->ld_errno = LDAP_ENCODING_ERROR;
        ber_free( ber, 1 );
        return( NULL );
    }

    return( ber );
}
Exemple #17
0
int
ldap_create_vlv_control_value(
	LDAP *ld,
	LDAPVLVInfo *vlvinfop,
	struct berval *value )
{
	ber_tag_t tag;
	BerElement *ber;

	if ( ld == NULL || vlvinfop == NULL || value == NULL ) {
		if ( ld )
			ld->ld_errno = LDAP_PARAM_ERROR;
		return LDAP_PARAM_ERROR;
	}

	assert( LDAP_VALID( ld ) );

	value->bv_val = NULL;
	value->bv_len = 0;
	ld->ld_errno = LDAP_SUCCESS;

	ber = ldap_alloc_ber_with_options( ld );
	if ( ber == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	tag = ber_printf( ber, "{ii" /*}*/,
		vlvinfop->ldvlv_before_count,
		vlvinfop->ldvlv_after_count );
	if ( tag == LBER_ERROR ) {
		goto error_return;
	}

	if ( vlvinfop->ldvlv_attrvalue == NULL ) {
		tag = ber_printf( ber, "t{iiN}",
			LDAP_VLVBYINDEX_IDENTIFIER,
			vlvinfop->ldvlv_offset,
			vlvinfop->ldvlv_count );
		if ( tag == LBER_ERROR ) {
			goto error_return;
		}

	} else {
		tag = ber_printf( ber, "tO",
			LDAP_VLVBYVALUE_IDENTIFIER,
			vlvinfop->ldvlv_attrvalue );
		if ( tag == LBER_ERROR ) {
			goto error_return;
		}
	}

	if ( vlvinfop->ldvlv_context ) {
		tag = ber_printf( ber, "tO",
			LDAP_VLVCONTEXT_IDENTIFIER,
			vlvinfop->ldvlv_context );
		if ( tag == LBER_ERROR ) {
			goto error_return;
		}
	}

	tag = ber_printf( ber, /*{*/ "N}" ); 
	if ( tag == LBER_ERROR ) {
		goto error_return;
	}

	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
		ld->ld_errno = LDAP_NO_MEMORY;
	}

	if ( 0 ) {
error_return:;
		ld->ld_errno = LDAP_ENCODING_ERROR;
	}

	if ( ber != NULL ) {
		ber_free( ber, 1 );
	}

	return ld->ld_errno;
}
Exemple #18
0
int ber_encode_krb5_key_data(krb5_key_data *data,
                             int numk, int mkvno,
                             struct berval **encoded)
{
    BerElement *be = NULL;
    ber_tag_t tag;
    int ret, i;

    be = ber_alloc_t(LBER_USE_DER);
    if (!be) {
        return ENOMEM;
    }

    tag = LBER_CONSTRUCTED | LBER_CLASS_CONTEXT;

    ret = ber_printf(be, "{t[i]t[i]t[i]t[i]t[{",
                         tag | 0, 1, tag | 1, 1,
                         tag | 2, (ber_int_t)data[0].key_data_kvno,
                         tag | 3, (ber_int_t)mkvno, tag | 4);
    if (ret == -1) {
        ret = EFAULT;
        goto done;
    }

    for (i = 0; i < numk; i++) {

        ret = ber_printf(be, "{");
        if (ret == -1) {
            ret = EFAULT;
            goto done;
        }

        if (data[i].key_data_length[1] != 0) {
            ret = ber_printf(be, "t[{t[i]",
                                 tag | 0,
                                   tag | 0,
                                     (ber_int_t)data[i].key_data_type[1]);
            if (ret != -1) {
                ret = ber_printf(be, "t[o]",
                                     tag | 1,
                                       data[i].key_data_contents[1],
                                       (ber_len_t)data[i].key_data_length[1]);
            }
            if (ret != -1) {
                ret = ber_printf(be, "}]");
            }
            if (ret == -1) {
                ret = EFAULT;
                goto done;
            }
        }

        ret = ber_printf(be, "t[{t[i]t[o]}]",
                              tag | 1,
                                tag | 0,
                                  (ber_int_t)data[i].key_data_type[0],
                                tag | 1,
                                  data[i].key_data_contents[0],
                                  (ber_len_t)data[i].key_data_length[0]);
        if (ret == -1) {
            ret = EFAULT;
            goto done;
        }

        ret = ber_printf(be, "}");
        if (ret == -1) {
            ret = EFAULT;
            goto done;
        }
    }

    ret = ber_printf(be, "}]}");
    if (ret == -1) {
        ret = EFAULT;
        goto done;
    }

    ret = ber_flatten(be, encoded);
    if (ret == -1) {
        ret = EFAULT;
        goto done;
    }

done:
    ber_free(be, 1);
    return ret;
}
Exemple #19
0
/***********************************************************************
 *      ber_printf     (WLDAP32.@)
 *
 * Encode a berelement structure.
 *
 * PARAMS
 *  berelement [I/O] Pointer to a berelement structure.
 *  fmt        [I]   Format string.
 *  ...        [I]   Values to encode.
 *
 * RETURNS
 *  Success: Non-negative number. 
 *  Failure: LBER_ERROR
 *
 * NOTES
 *  berelement must have been allocated with ber_alloc_t. This function
 *  can be called multiple times to append data.
 */
INT CDECL WLDAP32_ber_printf( BerElement *berelement, PCHAR fmt, ... )
{
#ifdef HAVE_LDAP
    __ms_va_list list;
    int ret = 0;
    char new_fmt[2];

    new_fmt[1] = 0;
    __ms_va_start( list, fmt );
    while (*fmt)
    {
        new_fmt[0] = *fmt++;
        switch(new_fmt[0])
        {
        case 'b':
        case 'e':
        case 'i':
            {
                int i = va_arg( list, int );
                ret = ber_printf( berelement, new_fmt, i );
                break;
            }
        case 'o':
        case 's':
            {
                char *str = va_arg( list, char * );
                ret = ber_printf( berelement, new_fmt, str );
                break;
            }
        case 't':
            {
                unsigned int tag = va_arg( list, unsigned int );
                ret = ber_printf( berelement, new_fmt, tag );
                break;
            }
        case 'v':
            {
                char **array = va_arg( list, char ** );
                ret = ber_printf( berelement, new_fmt, array );
                break;
            }
        case 'V':
            {
                struct berval **array = va_arg( list, struct berval ** );
                ret = ber_printf( berelement, new_fmt, array );
                break;
            }
        case 'X':
            {
                char *str = va_arg( list, char * );
                int len = va_arg( list, int );
                new_fmt[0] = 'B';  /* 'X' is deprecated */
                ret = ber_printf( berelement, new_fmt, str, len );
                break;
            }
        case 'n':
        case '{':
        case '}':
        case '[':
        case ']':
            ret = ber_printf( berelement, new_fmt );
            break;
        default:
            FIXME( "Unknown format '%c'\n", new_fmt[0] );
            ret = -1;
            break;
        }
        if (ret == -1) break;
    }
    __ms_va_end( list );
    return ret;
#else
    return LBER_ERROR;
#endif
}
Exemple #20
0
struct berval *create_key_control(struct keys_container *keys,
                                  const char *principalName)
{
    struct krb_key_salt *ksdata;
    struct berval *bval;
    BerElement *be;
    int ret, i;

    be = ber_alloc_t(LBER_USE_DER);
    if (!be) {
        return NULL;
    }

    ret = ber_printf(be, "{s{", principalName);
    if (ret == -1) {
        ber_free(be, 1);
        return NULL;
    }

    ksdata = keys->ksdata;
    for (i = 0; i < keys->nkeys; i++) {

        /* we set only the EncryptionKey and salt, no s2kparams */

        ret = ber_printf(be, "{t[{t[i]t[o]}]",
                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
                 (ber_int_t)ksdata[i].enctype,
                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
                 (char *)ksdata[i].key.contents, (ber_len_t)ksdata[i].key.length);

        if (ret == -1) {
            ber_free(be, 1);
            return NULL;
        }

        if (ksdata[i].salttype == NO_SALT) {
            ret = ber_printf(be, "}");
            continue;
        }

        /* we have to pass a salt structure */
        ret = ber_printf(be, "t[{t[i]t[o]}]}",
                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0),
                 (ber_int_t)ksdata[i].salttype,
                 (ber_tag_t)(LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1),
                 (char *)ksdata[i].salt.data, (ber_len_t)ksdata[i].salt.length);

        if (ret == -1) {
            ber_free(be, 1);
            return NULL;
        }
    }

    ret = ber_printf(be, "}}");
    if (ret == -1) {
        ber_free(be, 1);
        return NULL;
    }

    ret = ber_flatten(be, &bval);
    if (ret == -1) {
        ber_free(be, 1);
        return NULL;
    }

    ber_free(be, 1);
    return bval;
}
Exemple #21
0
/*
 * ldap_sasl_bind - authenticate to the ldap server.  The dn, mechanism,
 * and credentials of the entry to which to bind are supplied. An LDAP
 * error code is returned and if LDAP_SUCCESS is returned *msgidp is set
 * to the id of the request initiated.
 *
 * Example:
 *	struct berval	creds;
 *	LDAPControl	**ctrls;
 *	int		err, msgid;
 *	... fill in creds with credentials ...
 *	... fill in ctrls with server controls ...
 *	err = ldap_sasl_bind( ld, "cn=manager, o=university of michigan, c=us",
 *	    "mechanismname", &creds, ctrls, NULL, &msgid );
 */
int
LDAP_CALL
ldap_sasl_bind(
    LDAP		*ld,
    const char		*dn,
    const char		*mechanism,
    const struct berval	*cred,
    LDAPControl		**serverctrls,
    LDAPControl		**clientctrls,
    int			*msgidp
)
{
	BerElement	*ber;
	int		rc, simple, msgid, ldapversion;

	/*
	 * The ldapv3 bind request looks like this:
	 *	BindRequest ::= SEQUENCE {
	 *		version		INTEGER,
	 *		name		DistinguishedName,	 -- who
	 *		authentication	CHOICE {
	 *			simple		[0] OCTET STRING, -- passwd
	 *			sasl		[3] SaslCredentials -- v3 only
	 *		}
	 *	}
	 *	SaslCredentials ::= SEQUENCE {
	 *		mechanism	LDAPString,
	 * 		credentials	OCTET STRING
	 *	}
	 * all wrapped up in an LDAPMessage sequence.
	 */

	LDAPDebug( LDAP_DEBUG_TRACE, "ldap_sasl_bind\n", 0, 0, 0 );

	if ( msgidp == NULL ) {
		LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
                return( LDAP_PARAM_ERROR );
	}

	simple = ( mechanism == LDAP_SASL_SIMPLE );
	ldapversion = NSLDAPI_LDAP_VERSION( ld );

	/* only ldapv3 or higher can do sasl binds */
	if ( !simple && ldapversion < LDAP_VERSION3 ) {
		LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL );
		return( LDAP_NOT_SUPPORTED );
	}

	LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK );
	msgid = ++ld->ld_msgid;
	LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK );

	if ( dn == NULL )
		dn = "";

	if ( ld->ld_cache_on && ld->ld_cache_bind != NULL ) {
		LDAP_MUTEX_LOCK( ld, LDAP_CACHE_LOCK );
		if ( (rc = (ld->ld_cache_bind)( ld, msgid, LDAP_REQ_BIND, dn,
		    cred, LDAP_AUTH_SASL )) != 0 ) {
			*msgidp = rc;
			LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
			return( LDAP_SUCCESS );
		}
		LDAP_MUTEX_UNLOCK( ld, LDAP_CACHE_LOCK );
	}

	/* create a message to send */
	if (( rc = nsldapi_alloc_ber_with_options( ld, &ber ))
	    != LDAP_SUCCESS ) {
		return( rc );
	}

	/* fill it in */
	if ( simple ) {		/* simple bind; works in LDAPv2 or v3 */
		struct berval	tmpcred;

		if ( cred == NULL ) {
			tmpcred.bv_val = "";
			tmpcred.bv_len = 0;
			cred = &tmpcred;
		}
		rc = ber_printf( ber, "{it{isto}", msgid, LDAP_REQ_BIND,
		    ldapversion, dn, LDAP_AUTH_SIMPLE, cred->bv_val,
		    (int)cred->bv_len /* XXX lossy cast */ );

	} else {		/* SASL bind; requires LDAPv3 or better */
		if ( cred == NULL ) {
			rc = ber_printf( ber, "{it{ist{s}}", msgid,
			    LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SASL,
			    mechanism );
		} else {
			rc = ber_printf( ber, "{it{ist{so}}", msgid,
			    LDAP_REQ_BIND, ldapversion, dn, LDAP_AUTH_SASL,
			    mechanism, cred->bv_val,
			    (int)cred->bv_len /* XXX lossy cast */ );
		}
	}

	if ( rc == -1 ) {
		LDAP_SET_LDERRNO( ld, LDAP_ENCODING_ERROR, NULL, NULL );
		ber_free( ber, 1 );
		return( LDAP_ENCODING_ERROR );
	}

	if ( (rc = nsldapi_put_controls( ld, serverctrls, 1, ber ))
	    != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return( rc );
	}

	/* send the message */
	rc = nsldapi_send_initial_request( ld, msgid, LDAP_REQ_BIND,
		(char *)dn, ber );
	*msgidp = rc;
	return( rc < 0 ? LDAP_GET_LDERRNO( ld, NULL, NULL ) : LDAP_SUCCESS );
}
Exemple #22
0
/*
 * ldap_modify_ext - initiate an ldap extended modify operation.
 *
 * Parameters:
 *
 *	ld		LDAP descriptor
 *	dn		DN of the object to modify
 *	mods		List of modifications to make.  This is null-terminated
 *			array of struct ldapmod's, specifying the modifications
 *			to perform.
 *	sctrls	Server Controls
 *	cctrls	Client Controls
 *	msgidp	Message ID pointer
 *
 * Example:
 *	LDAPMod	*mods[] = { 
 *			{ LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } },
 *			{ LDAP_MOD_REPLACE, "sn", { "jensen", 0 } },
 *			0
 *		}
 *	rc=  ldap_modify_ext( ld, dn, mods, sctrls, cctrls, &msgid );
 */
int
ldap_modify_ext( LDAP *ld,
	LDAP_CONST char *dn,
	LDAPMod **mods,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	int *msgidp )
{
	BerElement	*ber;
	int		i, rc;

	/*
	 * A modify request looks like this:
	 *	ModifyRequet ::= SEQUENCE {
	 *		object		DistinguishedName,
	 *		modifications	SEQUENCE OF SEQUENCE {
	 *			operation	ENUMERATED {
	 *				add	(0),
	 *				delete	(1),
	 *				replace	(2)
	 *			},
	 *			modification	SEQUENCE {
	 *				type	AttributeType,
	 *				values	SET OF AttributeValue
	 *			}
	 *		}
	 *	}
	 */

#ifdef NEW_LOGGING
	LDAP_LOG ( OPERATION, ENTRY, "ldap_modify_ext\n", 0, 0, 0 );
#else
	Debug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 );
#endif

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( LDAP_NO_MEMORY );
	}

	if ( ber_printf( ber, "{it{s{" /*}}}*/, ++ld->ld_msgid, LDAP_REQ_MODIFY, dn )
	    == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* for each modification to be performed... */
	for ( i = 0; mods[i] != NULL; i++ ) {
		if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
			rc = ber_printf( ber, "{e{s[V]N}N}",
			    (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ),
			    mods[i]->mod_type, mods[i]->mod_bvalues );
		} else {
			rc = ber_printf( ber, "{e{s[v]N}N}",
				(ber_int_t) mods[i]->mod_op,
			    mods[i]->mod_type, mods[i]->mod_values );
		}

		if ( rc == -1 ) {
			ld->ld_errno = LDAP_ENCODING_ERROR;
			ber_free( ber, 1 );
			return( ld->ld_errno );
		}
	}

	if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber );
	return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
}
Exemple #23
0
int
ldap_create_sort_control_value(
	LDAP *ld,
	LDAPSortKey **keyList,
	struct berval *value )
{
	int		i;
	BerElement	*ber = NULL;
	ber_tag_t	tag;

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );

	if ( ld == NULL ) return LDAP_PARAM_ERROR;
	if ( keyList == NULL || value == NULL ) {
		ld->ld_errno = LDAP_PARAM_ERROR;
		return LDAP_PARAM_ERROR;
	}

	value->bv_val = NULL;
	value->bv_len = 0;
	ld->ld_errno = LDAP_SUCCESS;

	ber = ldap_alloc_ber_with_options( ld );
	if ( ber == NULL) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	tag = ber_printf( ber, "{" /*}*/ );
	if ( tag == LBER_ERROR ) {
		goto error_return;
	}

	for ( i = 0; keyList[i] != NULL; i++ ) {
		tag = ber_printf( ber, "{s" /*}*/, keyList[i]->attributeType );
		if ( tag == LBER_ERROR ) {
			goto error_return;
		}

		if ( keyList[i]->orderingRule != NULL ) {
			tag = ber_printf( ber, "ts",
				LDAP_MATCHRULE_IDENTIFIER,
				keyList[i]->orderingRule );

			if ( tag == LBER_ERROR ) {
				goto error_return;
			}
		}

		if ( keyList[i]->reverseOrder ) {
			tag = ber_printf( ber, "tb",
				LDAP_REVERSEORDER_IDENTIFIER,
				keyList[i]->reverseOrder );

			if ( tag == LBER_ERROR ) {
				goto error_return;
			}
		}

		tag = ber_printf( ber, /*{*/ "N}" );
		if ( tag == LBER_ERROR ) {
			goto error_return;
		}
	}

	tag = ber_printf( ber, /*{*/ "N}" );
	if ( tag == LBER_ERROR ) {
		goto error_return;
	}

	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
		ld->ld_errno = LDAP_NO_MEMORY;
	}

	if ( 0 ) {
error_return:;
		ld->ld_errno =  LDAP_ENCODING_ERROR;
	}

	if ( ber != NULL ) {
		ber_free( ber, 1 );
	}

	return ld->ld_errno;
}
int
ldap_extended_operation(
	LDAP			*ld,
	LDAP_CONST char	*reqoid,
	struct berval	*reqdata,
	LDAPControl		**sctrls,
	LDAPControl		**cctrls,
	int				*msgidp )
{
	BerElement *ber;
	int rc;
	ber_int_t id;

	Debug( LDAP_DEBUG_TRACE, "ldap_extended_operation\n", 0, 0, 0 );

	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( reqoid != NULL && *reqoid != '\0' );
	assert( msgidp != NULL );

	/* must be version 3 (or greater) */
	if ( ld->ld_version < LDAP_VERSION3 ) {
		ld->ld_errno = LDAP_NOT_SUPPORTED;
		return( ld->ld_errno );
	}

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return( ld->ld_errno );
	}

	LDAP_NEXT_MSGID( ld, id );
	if ( reqdata != NULL ) {
		rc = ber_printf( ber, "{it{tstON}", /* '}' */
			id, LDAP_REQ_EXTENDED,
			LDAP_TAG_EXOP_REQ_OID, reqoid,
			LDAP_TAG_EXOP_REQ_VALUE, reqdata );

	} else {
		rc = ber_printf( ber, "{it{tsN}", /* '}' */
			id, LDAP_REQ_EXTENDED,
			LDAP_TAG_EXOP_REQ_OID, reqoid );
	}

	if( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_EXTENDED, NULL, ber, id );

	return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
}
Exemple #25
0
/* returns an LDAP error code */
static int
re_encode_request( LDAP *ld, BerElement *origber, int msgid, LDAPURLDesc *ludp,
    BerElement **berp )
{
/*
 * XXX this routine knows way too much about how the lber library works!
 */
	ber_uint_t		along;
	ber_tag_t		tag;
	ber_int_t		ver;
	int			rc;
	BerElement		*ber;
	struct berelement	tmpber;
	char			*dn, *orig_dn;

	LDAPDebug( LDAP_DEBUG_TRACE,
	    "re_encode_request: new msgid %d, new dn <%s>\n",
	    msgid, ( ludp->lud_dn == NULL ) ? "NONE" : ludp->lud_dn, 0 );

	tmpber = *origber;

	/*
	 * All LDAP requests are sequences that start with a message id.  For
	 * everything except delete requests, this is followed by a sequence
	 * that is tagged with the operation code.  For deletes, there is just
	 * a DN that is tagged with the operation code.
	 */

	/* skip past msgid and get operation tag */
	if ( ber_scanf( &tmpber, "{it", &along, &tag ) == LBER_ERROR ) {
		return( LDAP_DECODING_ERROR );
	}

	/*
	 * XXXmcs: we don't support scope or filters in search referrals yet,
	 * so if either were present we return an error which is probably
	 * better than just ignoring the extra info.
	 */
	if ( tag == LDAP_REQ_SEARCH &&
	    ( ludp->lud_scope != -1 || ludp->lud_filter != NULL )) {
		return( LDAP_LOCAL_ERROR );
	}

	if ( tag == LDAP_REQ_BIND ) {
		/* bind requests have a version number before the DN */
		rc = ber_scanf( &tmpber, "{ia", &ver, &orig_dn );
	} else if ( tag == LDAP_REQ_DELETE ) {
		/* delete requests DNs are not within a sequence */
		rc = ber_scanf( &tmpber, "a", &orig_dn );
	} else {
		rc = ber_scanf( &tmpber, "{a", &orig_dn );
	}

	if ( rc == LBER_ERROR ) {
		return( LDAP_DECODING_ERROR );
	}

	if ( ludp->lud_dn == NULL ) {
		dn = orig_dn;
	} else {
		dn = ludp->lud_dn;
		NSLDAPI_FREE( orig_dn );
		orig_dn = NULL;
	}

	/* allocate and build the new request */
        if (( rc = nsldapi_alloc_ber_with_options( ld, &ber ))
	    != LDAP_SUCCESS ) {
		if ( orig_dn != NULL ) {
			NSLDAPI_FREE( orig_dn );
		}
                return( rc );
        }

	if ( tag == LDAP_REQ_BIND ) {
		rc = ber_printf( ber, "{it{is", msgid, tag,
		    (int)ver /* XXX lossy cast */, dn );
	} else if ( tag == LDAP_REQ_DELETE ) {
		rc = ber_printf( ber, "{its}", msgid, tag, dn );
	} else {
		rc = ber_printf( ber, "{it{s", msgid, tag, dn );
	}

	if ( orig_dn != NULL ) {
		NSLDAPI_FREE( orig_dn );
	}
/*
 * can't use "dn" or "orig_dn" from this point on (they've been freed)
 */

	if ( rc == -1 ) {
		ber_free( ber, 1 );
		return( LDAP_ENCODING_ERROR );
	}

	if ( tag != LDAP_REQ_DELETE &&
	    ( ber_write( ber, tmpber.ber_ptr, ( tmpber.ber_end -
	    tmpber.ber_ptr ), 0 ) != ( tmpber.ber_end - tmpber.ber_ptr )
	    || ber_printf( ber, "}}" ) == -1 )) {
		ber_free( ber, 1 );
		return( LDAP_ENCODING_ERROR );
	}

#ifdef LDAP_DEBUG
	if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
		LDAPDebug( LDAP_DEBUG_ANY, "re_encode_request new request is:\n",
		    0, 0, 0 );
		ber_dump( ber, 0 );
	}
#endif /* LDAP_DEBUG */

	*berp = ber;
	return( LDAP_SUCCESS );
}
Exemple #26
0
int
ldap_create_session_tracking_value(
	LDAP		*ld,
	char		*sessionSourceIp,
	char		*sessionSourceName,
	char		*formatOID,
	struct berval	*sessionTrackingIdentifier,
	struct berval	*value )
{
	BerElement	*ber = NULL;
	ber_tag_t	tag;

	struct berval	ip, name, oid, id;

	if ( ld == NULL ||
		formatOID == NULL ||
		value == NULL )
	{
param_error:;
		if ( ld ) {
			ld->ld_errno = LDAP_PARAM_ERROR;
		}

		return LDAP_PARAM_ERROR;
	}

	assert( LDAP_VALID( ld ) );
	ld->ld_errno = LDAP_SUCCESS;

	/* check sizes according to I.D. */
	if ( sessionSourceIp == NULL ) {
		BER_BVSTR( &ip, "" );

	} else {
		ber_str2bv( sessionSourceIp, 0, 0, &ip );
		/* NOTE: we're strict because we don't want
		 * to send out bad data */
		if ( ip.bv_len > 128 ) goto param_error;
	}

	if ( sessionSourceName == NULL ) {
		BER_BVSTR( &name, "" );

	} else {
		ber_str2bv( sessionSourceName, 0, 0, &name );
		/* NOTE: we're strict because we don't want
		 * to send out bad data */
		if ( name.bv_len > 65536 ) goto param_error;
	}

	ber_str2bv( formatOID, 0, 0, &oid );
	/* NOTE: we're strict because we don't want
	 * to send out bad data */
	if ( oid.bv_len > 1024 ) goto param_error;

	if ( sessionTrackingIdentifier == NULL ||
		sessionTrackingIdentifier->bv_val == NULL )
	{
		BER_BVSTR( &id, "" );

	} else {
		id = *sessionTrackingIdentifier;
	}

	/* prepare value */
	value->bv_val = NULL;
	value->bv_len = 0;

	ber = ldap_alloc_ber_with_options( ld );
	if ( ber == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	tag = ber_printf( ber, "{OOOO}", &ip, &name, &oid, &id );
	if ( tag == LBER_ERROR ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		goto done;
	}

	if ( ber_flatten2( ber, value, 1 ) == -1 ) {
		ld->ld_errno = LDAP_NO_MEMORY;
	}

done:;
	if ( ber != NULL ) {
		ber_free( ber, 1 );
	}

	return ld->ld_errno;
}
Exemple #27
0
static BerElement *
re_encode_request( LDAP *ld,
	BerElement *origber,
	ber_int_t msgid,
	int sref,
	LDAPURLDesc *srv,
	int *type )
{
	/*
	 * XXX this routine knows way too much about how the lber library works!
	 */
	ber_int_t	along;
	ber_tag_t	tag;
	ber_tag_t	rtag;
	ber_int_t	ver;
	ber_int_t	scope;
	int		rc;
	BerElement	tmpber, *ber;
	struct berval		dn;

	Debug( LDAP_DEBUG_TRACE,
	    "re_encode_request: new msgid %ld, new dn <%s>\n",
	    (long) msgid,
		( srv == NULL || srv->lud_dn == NULL) ? "NONE" : srv->lud_dn, 0 );

	tmpber = *origber;

	/*
	 * all LDAP requests are sequences that start with a message id.
	 * For all except delete, this is followed by a sequence that is
	 * tagged with the operation code.  For delete, the provided DN
	 * is not wrapped by a sequence.
	 */
	rtag = ber_scanf( &tmpber, "{it", /*}*/ &along, &tag );

	if ( rtag == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		return( NULL );
	}

	assert( tag != 0);
	if ( tag == LDAP_REQ_BIND ) {
		/* bind requests have a version number before the DN & other stuff */
		rtag = ber_scanf( &tmpber, "{im" /*}*/, &ver, &dn );

	} else if ( tag == LDAP_REQ_DELETE ) {
		/* delete requests don't have a DN wrapping sequence */
		rtag = ber_scanf( &tmpber, "m", &dn );

	} else if ( tag == LDAP_REQ_SEARCH ) {
		/* search requests need to be re-scope-ed */
		rtag = ber_scanf( &tmpber, "{me" /*"}"*/, &dn, &scope );

		if( srv->lud_scope != LDAP_SCOPE_DEFAULT ) {
			/* use the scope provided in reference */
			scope = srv->lud_scope;

		} else if ( sref ) {
			/* use scope implied by previous operation
			 *   base -> base
			 *   one -> base
			 *   subtree -> subtree
			 *   subordinate -> subtree
			 */
			switch( scope ) {
			default:
			case LDAP_SCOPE_BASE:
			case LDAP_SCOPE_ONELEVEL:
				scope = LDAP_SCOPE_BASE;
				break;
			case LDAP_SCOPE_SUBTREE:
			case LDAP_SCOPE_SUBORDINATE:
				scope = LDAP_SCOPE_SUBTREE;
				break;
			}
		}

	} else {
		rtag = ber_scanf( &tmpber, "{m" /*}*/, &dn );
	}

	if( rtag == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		return NULL;
	}

	/* restore character zero'd out by ber_scanf*/
	dn.bv_val[dn.bv_len] = tmpber.ber_tag;

	if (( ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return NULL;
	}

	if ( srv->lud_dn ) {
		ber_str2bv( srv->lud_dn, 0, 0, &dn );
	}

	if ( tag == LDAP_REQ_BIND ) {
		rc = ber_printf( ber, "{it{iO" /*}}*/, msgid, tag, ver, &dn );
	} else if ( tag == LDAP_REQ_DELETE ) {
		rc = ber_printf( ber, "{itON}", msgid, tag, &dn );
	} else if ( tag == LDAP_REQ_SEARCH ) {
		rc = ber_printf( ber, "{it{Oe" /*}}*/, msgid, tag, &dn, scope );
	} else {
		rc = ber_printf( ber, "{it{O" /*}}*/, msgid, tag, &dn );
	}

	if ( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return NULL;
	}

	if ( tag != LDAP_REQ_DELETE && (
		ber_write(ber, tmpber.ber_ptr, ( tmpber.ber_end - tmpber.ber_ptr ), 0)
		!= ( tmpber.ber_end - tmpber.ber_ptr ) ||
	    ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) )
	{
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return NULL;
	}

#ifdef LDAP_DEBUG
	if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
		Debug( LDAP_DEBUG_ANY, "re_encode_request new request is:\n",
		    0, 0, 0 );
		ber_log_dump( LDAP_DEBUG_BER, ldap_debug, ber, 0 );
	}
#endif /* LDAP_DEBUG */

	*type = tag;	/* return request type */
	return ber;
}
Exemple #28
0
/*
 * ldap_modify_ext - initiate an ldap extended modify operation.
 *
 * Parameters:
 *
 *	ld		LDAP descriptor
 *	dn		DN of the object to modify
 *	mods		List of modifications to make.  This is null-terminated
 *			array of struct ldapmod's, specifying the modifications
 *			to perform.
 *	sctrls	Server Controls
 *	cctrls	Client Controls
 *	msgidp	Message ID pointer
 *
 * Example:
 *	LDAPMod	*mods[] = { 
 *			{ LDAP_MOD_ADD, "cn", { "babs jensen", "babs", 0 } },
 *			{ LDAP_MOD_REPLACE, "sn", { "babs jensen", "babs", 0 } },
 *			{ LDAP_MOD_DELETE, "ou", 0 },
 *			{ LDAP_MOD_INCREMENT, "uidNumber, { "1", 0 } }
 *			0
 *		}
 *	rc=  ldap_modify_ext( ld, dn, mods, sctrls, cctrls, &msgid );
 */
int
ldap_modify_ext( LDAP *ld,
	LDAP_CONST char *dn,
	LDAPMod **mods,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	int *msgidp )
{
	BerElement	*ber;
	int		i, rc;
	ber_int_t	id;

	Debug( LDAP_DEBUG_TRACE, "ldap_modify_ext\n", 0, 0, 0 );

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		return( LDAP_NO_MEMORY );
	}

	LDAP_NEXT_MSGID( ld, id );
	rc = ber_printf( ber, "{it{s{" /*}}}*/, id, LDAP_REQ_MODIFY, dn );
	if ( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* allow mods to be NULL ("touch") */
	if ( mods ) {
		/* for each modification to be performed... */
		for ( i = 0; mods[i] != NULL; i++ ) {
			if (( mods[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
				rc = ber_printf( ber, "{e{s[V]N}N}",
				    (ber_int_t) ( mods[i]->mod_op & ~LDAP_MOD_BVALUES ),
				    mods[i]->mod_type, mods[i]->mod_bvalues );
			} else {
				rc = ber_printf( ber, "{e{s[v]N}N}",
					(ber_int_t) mods[i]->mod_op,
				    mods[i]->mod_type, mods[i]->mod_values );
			}

			if ( rc == -1 ) {
				ld->ld_errno = LDAP_ENCODING_ERROR;
				ber_free( ber, 1 );
				return( ld->ld_errno );
			}
		}
	}

	if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return( ld->ld_errno );
	}

	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_MODIFY, dn, ber, id );
	return( *msgidp < 0 ? ld->ld_errno : LDAP_SUCCESS );
}
Exemple #29
0
static int
put_simple_filter(
	BerElement *ber,
	char *str )
{
	char		*s;
	char		*value;
	ber_tag_t	ftype;
	int		rc = -1;

	Debug( LDAP_DEBUG_TRACE, "put_simple_filter: \"%s\"\n",
		str, 0, 0 );

	str = LDAP_STRDUP( str );
	if( str == NULL ) return -1;

	if ( (s = strchr( str, '=' )) == NULL ) {
		goto done;
	}

	value = s + 1;
	*s-- = '\0';

	switch ( *s ) {
	case '<':
		ftype = LDAP_FILTER_LE;
		*s = '\0';
		break;

	case '>':
		ftype = LDAP_FILTER_GE;
		*s = '\0';
		break;

	case '~':
		ftype = LDAP_FILTER_APPROX;
		*s = '\0';
		break;

	case ':':
		/* RFC 4515 extensible filters are off the form:
		 *		type [:dn] [:rule] := value
		 * or	[:dn]:rule := value		
		 */
		ftype = LDAP_FILTER_EXT;
		*s = '\0';

		{
			char *dn = strchr( str, ':' );
			char *rule = NULL;

			if( dn != NULL ) {
				*dn++ = '\0';
				rule = strchr( dn, ':' );

				if( rule == NULL ) {
					/* one colon */
					if ( strcasecmp(dn, "dn") == 0 ) {
						/* must have attribute */
						if( !ldap_is_desc( str ) ) {
							goto done;
						}

						rule = "";

					} else {
					  rule = dn;
					  dn = NULL;
					}
				
				} else {
					/* two colons */
					*rule++ = '\0';

					if ( strcasecmp(dn, "dn") != 0 ) {
						/* must have "dn" */
						goto done;
					}
				}

			}

			if ( *str == '\0' && ( !rule || *rule == '\0' ) ) {
				/* must have either type or rule */
				goto done;
			}

			if ( *str != '\0' && !ldap_is_desc( str ) ) {
				goto done;
			}

			if ( rule && *rule != '\0' && !ldap_is_oid( rule ) ) {
				goto done;
			}

			rc = ber_printf( ber, "t{" /*"}"*/, ftype );

			if( rc != -1 && rule && *rule != '\0' ) {
				rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_OID, rule );
			}

			if( rc != -1 && *str != '\0' ) {
				rc = ber_printf( ber, "ts", LDAP_FILTER_EXT_TYPE, str );
			}

			if( rc != -1 ) {
				ber_slen_t len = ldap_pvt_filter_value_unescape( value );

				if( len >= 0 ) {
					rc = ber_printf( ber, "to",
						LDAP_FILTER_EXT_VALUE, value, len );
				} else {
					rc = -1;
				}
			}

			if( rc != -1 && dn ) {
				rc = ber_printf( ber, "tb",
					LDAP_FILTER_EXT_DNATTRS, (ber_int_t) 1 );
			}

			if( rc != -1 ) { 
				rc = ber_printf( ber, /*"{"*/ "N}" );
			}
		}
		goto done;

	default:
		if( !ldap_is_desc( str ) ) {
			goto done;

		} else {
			char *nextstar = ldap_pvt_find_wildcard( value );

			if ( nextstar == NULL ) {
				goto done;

			} else if ( *nextstar == '\0' ) {
				ftype = LDAP_FILTER_EQUALITY;

			} else if ( strcmp( value, "*" ) == 0 ) {
				ftype = LDAP_FILTER_PRESENT;

			} else {
				rc = put_substring_filter( ber, str, value, nextstar );
				goto done;
			}
		} break;
	}

	if( !ldap_is_desc( str ) ) goto done;

	if ( ftype == LDAP_FILTER_PRESENT ) {
		rc = ber_printf( ber, "ts", ftype, str );

	} else {
		ber_slen_t len = ldap_pvt_filter_value_unescape( value );

		if( len >= 0 ) {
			rc = ber_printf( ber, "t{soN}",
				ftype, str, value, len );
		}
	}

done:
	if( rc != -1 ) rc = 0;
	LDAP_FREE( str );
	return rc;
}
Exemple #30
0
/*
 * ldap_add_ext - initiate an ldap extended add operation.  Parameters:
 *
 *	ld		LDAP descriptor
 *	dn		DN of the entry to add
 *	mods		List of attributes for the entry.  This is a null-
 *			terminated array of pointers to LDAPMod structures.
 *			only the type and values in the structures need be
 *			filled in.
 *	sctrl	Server Controls
 *	cctrl	Client Controls
 *	msgidp	Message ID pointer
 *
 * Example:
 *	LDAPMod	*attrs[] = { 
 *			{ 0, "cn", { "babs jensen", "babs", 0 } },
 *			{ 0, "sn", { "jensen", 0 } },
 *			{ 0, "objectClass", { "person", 0 } },
 *			0
 *		}
 *	rc = ldap_add_ext( ld, dn, attrs, NULL, NULL, &msgid );
 */
int
ldap_add_ext(
	LDAP *ld,
	LDAP_CONST char *dn,
	LDAPMod **attrs,
	LDAPControl **sctrls,
	LDAPControl **cctrls,
	int	*msgidp )
{
	BerElement	*ber;
	int		i, rc;
	ber_int_t	id;

	Debug( LDAP_DEBUG_TRACE, "ldap_add_ext\n", 0, 0, 0 );
	assert( ld != NULL );
	assert( LDAP_VALID( ld ) );
	assert( dn != NULL );
	assert( msgidp != NULL );

	/* check client controls */
	rc = ldap_int_client_controls( ld, cctrls );
	if( rc != LDAP_SUCCESS ) return rc;

	/* create a message to send */
	if ( (ber = ldap_alloc_ber_with_options( ld )) == NULL ) {
		ld->ld_errno = LDAP_NO_MEMORY;
		return ld->ld_errno;
	}

	LDAP_NEXT_MSGID(ld, id);
	rc = ber_printf( ber, "{it{s{", /* '}}}' */
		id, LDAP_REQ_ADD, dn );

	if ( rc == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	/* allow attrs to be NULL ("touch"; should fail...) */
	if ( attrs ) {
		/* for each attribute in the entry... */
		for ( i = 0; attrs[i] != NULL; i++ ) {
			if ( ( attrs[i]->mod_op & LDAP_MOD_BVALUES) != 0 ) {
				int j;

				if ( attrs[i]->mod_bvalues == NULL ) {
					ld->ld_errno = LDAP_PARAM_ERROR;
					ber_free( ber, 1 );
					return ld->ld_errno;
				}

				for ( j = 0; attrs[i]->mod_bvalues[ j ] != NULL; j++ ) {
					if ( attrs[i]->mod_bvalues[ j ]->bv_val == NULL ) {
						ld->ld_errno = LDAP_PARAM_ERROR;
						ber_free( ber, 1 );
						return ld->ld_errno;
					}
				}

				rc = ber_printf( ber, "{s[V]N}", attrs[i]->mod_type,
				    attrs[i]->mod_bvalues );

			} else {
				if ( attrs[i]->mod_values == NULL ) {
					ld->ld_errno = LDAP_PARAM_ERROR;
					ber_free( ber, 1 );
					return ld->ld_errno;
				}

				rc = ber_printf( ber, "{s[v]N}", attrs[i]->mod_type,
				    attrs[i]->mod_values );
			}
			if ( rc == -1 ) {
				ld->ld_errno = LDAP_ENCODING_ERROR;
				ber_free( ber, 1 );
				return ld->ld_errno;
			}
		}
	}

	if ( ber_printf( ber, /*{{*/ "N}N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	/* Put Server Controls */
	if( ldap_int_put_controls( ld, sctrls, ber ) != LDAP_SUCCESS ) {
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	if ( ber_printf( ber, /*{*/ "N}" ) == -1 ) {
		ld->ld_errno = LDAP_ENCODING_ERROR;
		ber_free( ber, 1 );
		return ld->ld_errno;
	}

	/* send the message */
	*msgidp = ldap_send_initial_request( ld, LDAP_REQ_ADD, dn, ber, id );

	if(*msgidp < 0)
		return ld->ld_errno;

	return LDAP_SUCCESS;
}