~ubuntu-branches/ubuntu/raring/389-ds-base/raring

1 by Timo Aaltonen
Import upstream version 1.2.10.2
1
/** BEGIN COPYRIGHT BLOCK
2
 * This Program is free software; you can redistribute it and/or modify it under
3
 * the terms of the GNU General Public License as published by the Free Software
4
 * Foundation; version 2 of the License.
5
 * 
6
 * This Program is distributed in the hope that it will be useful, but WITHOUT
7
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9
 * 
10
 * You should have received a copy of the GNU General Public License along with
11
 * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
12
 * Place, Suite 330, Boston, MA 02111-1307 USA.
13
 * 
14
 * In addition, as a special exception, Red Hat, Inc. gives You the additional
15
 * right to link the code of this Program with code not covered under the GNU
16
 * General Public License ("Non-GPL Code") and to distribute linked combinations
17
 * including the two, subject to the limitations in this paragraph. Non-GPL Code
18
 * permitted under this exception must only link to the code of this Program
19
 * through those well defined interfaces identified in the file named EXCEPTION
20
 * found in the source code files (the "Approved Interfaces"). The files of
21
 * Non-GPL Code may instantiate templates or use macros or inline functions from
22
 * the Approved Interfaces without causing the resulting work to be covered by
23
 * the GNU General Public License. Only Red Hat, Inc. may make changes or
24
 * additions to the list of Approved Interfaces. You must obey the GNU General
25
 * Public License in all respects for all of the Program code and other code used
26
 * in conjunction with the Program except the Non-GPL Code covered by this
27
 * exception. If you modify this file, you may extend this exception to your
28
 * version of the file, but you are not obligated to do so. If you do not wish to
29
 * provide this exception without modification, you must delete this exception
30
 * statement from your version and license this file solely under the GPL without
31
 * exception. 
32
 * 
33
 * 
34
 * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
35
 * Copyright (C) 2005 Red Hat, Inc.
36
 * All rights reserved.
37
 * END COPYRIGHT BLOCK **/
38
39
#ifdef HAVE_CONFIG_H
40
#  include <config.h>
41
#endif
42
43
/* result.c - routines to send ldap results, errors, and referrals */
44
45
#include <stdio.h>
46
#include <string.h>
47
#include <sys/types.h>
48
#ifndef _WIN32
49
#include <sys/time.h>
50
#include <sys/socket.h>
51
#include <netinet/in.h>
52
#include <unistd.h>
53
#endif
54
#include <errno.h>
55
#include <signal.h>
56
#include "slap.h"
57
#include "pratom.h"
58
#include "fe.h"
59
#include "vattr_spi.h"
60
61
#include <ssl.h>
62
63
static Slapi_Counter *num_entries_sent;
64
static Slapi_Counter *num_bytes_sent;
65
66
static long	current_conn_count;
67
static PRLock	*current_conn_count_mutex;
68
69
static int flush_ber( Slapi_PBlock *pb, Connection *conn,
70
					  Operation *op, BerElement *ber, int type );
71
static char *notes2str( unsigned int notes, char *buf, size_t buflen );
72
static void log_result( Slapi_PBlock *pb, Operation *op, int err,
73
						ber_tag_t tag, int nentries );
74
static void log_entry( Operation *op, Slapi_Entry *e );
75
static void log_referral( Operation *op );
76
77
#define _LDAP_SEND_RESULT	0
78
#define _LDAP_SEND_REFERRAL	1
79
#define _LDAP_SEND_ENTRY	2
80
81
#define SLAPI_SEND_VATTR_FLAG_REALONLY          0x01
82
#define SLAPI_SEND_VATTR_FLAG_VIRTUALONLY       0x02
83
84
void g_set_num_entries_sent( Slapi_Counter *counter )
85
{
86
	num_entries_sent = counter;
87
}
88
89
PRUint64 g_get_num_entries_sent()
90
{
91
	return( slapi_counter_get_value(num_entries_sent) );
92
}
93
94
void g_set_num_bytes_sent( Slapi_Counter *counter )
95
{
96
	num_bytes_sent = counter;
97
}
98
99
PRUint64 g_get_num_bytes_sent()
100
{
101
	return( slapi_counter_get_value(num_bytes_sent) );
102
}
103
104
static void
105
delete_default_referral(struct berval **referrals)
106
{
107
	if (referrals)
108
	{
109
		int ii = 0;
110
		for (ii = 0; referrals[ii]; ++ii)
111
			ber_bvfree(referrals[ii]);
112
		slapi_ch_free((void**)&referrals);
113
	}
114
}
115
116
void 
117
g_set_default_referral( struct berval **ldap_url ) {
118
  struct berval       **default_referral;
119
  slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
120
  int nReferrals;
121
122
  /* check to see if we want to delete all referrals */
123
  if ( ldap_url && ldap_url[0] &&
124
	   PL_strncasecmp ( (char *)ldap_url[0]->bv_val, REFERRAL_REMOVE_CMD, ldap_url[0]->bv_len ) == 0 ) {
125
	delete_default_referral(slapdFrontendConfig->defaultreferral);
126
	slapdFrontendConfig->defaultreferral = NULL;
127
	return;
128
  }
129
130
  /* count the number of referrals */
131
  for ( nReferrals = 0; ldap_url && ldap_url[nReferrals]; nReferrals++ )
132
	;
133
  
134
  default_referral = (struct berval **) 
135
	slapi_ch_malloc( (nReferrals + 1) * sizeof(struct berval *) );
136
  
137
  /* terminate the end, and add the referrals backwards */
138
  default_referral[nReferrals--] = NULL;
139
140
  while ( nReferrals >= 0 ) {
141
	default_referral[nReferrals] = ber_bvdup(ldap_url[nReferrals]);
142
	nReferrals--;
143
  }
144
  
145
  delete_default_referral(slapdFrontendConfig->defaultreferral);
146
  slapdFrontendConfig->defaultreferral = default_referral;
147
}
148
149
struct berval**
150
g_get_default_referral() {
151
  slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
152
  return slapdFrontendConfig->defaultreferral;
153
}
154
155
/*
156
 * routines to manage keeping track of the current number of connections
157
 * to the server. this information is used by the listener thread to
158
 * determine when to stop listening for new connections, which it does
159
 * when the total number of descriptors available minus the number of
160
 * current connections drops below the reservedescriptors mark.
161
 */
162
163
void g_set_current_conn_count_mutex( PRLock *plock )
164
{
165
	PR_ASSERT( NULL != plock );
166
167
	current_conn_count_mutex = plock;
168
}
169
170
PRLock *g_get_current_conn_count_mutex()
171
{
172
	return( current_conn_count_mutex );
173
}
174
175
long g_get_current_conn_count()
176
{
177
	long	tmp;
178
179
	PR_ASSERT( NULL != current_conn_count_mutex );
180
181
	PR_Lock( current_conn_count_mutex );
182
	tmp = current_conn_count;
183
	PR_Unlock( current_conn_count_mutex );
184
185
	return( tmp );
186
}
187
188
void g_increment_current_conn_count()
189
{
190
	PR_ASSERT( NULL != current_conn_count_mutex );
191
192
	PR_Lock( current_conn_count_mutex );
193
	current_conn_count++;
194
	PR_Unlock( current_conn_count_mutex );
195
}
196
197
void g_decrement_current_conn_count()
198
{
199
	PR_ASSERT( NULL != current_conn_count_mutex );
200
201
	PR_Lock( current_conn_count_mutex );
202
	current_conn_count--;
203
/*	PR_ASSERT( current_conn_count >= 0 ); JCM BASTARD */
204
	PR_Unlock( current_conn_count_mutex );
205
}
206
207
208
void
209
send_ldap_result(
210
    Slapi_PBlock	*pb,
211
    int			err,
212
    char		*matched,
213
    char		*text,
214
    int			nentries,
215
    struct berval	**urls
216
)
217
{
218
       send_ldap_result_ext(pb, err, matched, text, nentries, urls, NULL);
219
}
220
221
222
static int
223
check_and_send_extended_result(Slapi_PBlock *pb, ber_tag_t tag, BerElement *ber)
224
{
225
	/*
226
	 * if this is an LDAPv3 ExtendedResponse to an ExtendedRequest,
227
	 * check to see if the optional responseName and response OCTET
228
	 * STRING need to be appended.
229
	 */
230
	int rc= 0;
231
	char *exop_oid;
232
	struct berval *exop_value;
233
	slapi_pblock_get(pb, SLAPI_EXT_OP_RET_OID, &exop_oid);
234
	slapi_pblock_get(pb, SLAPI_EXT_OP_RET_VALUE, &exop_value);
235
	if ( LDAP_RES_EXTENDED == tag ) {
236
		if (exop_oid != NULL) {
237
			rc = ber_printf( ber, "ts",
238
			    LDAP_TAG_EXOP_RES_OID, exop_oid);
239
		}
240
		if (rc != LBER_ERROR && exop_value != NULL) {
241
			rc = ber_printf( ber, "to",
242
			    LDAP_TAG_EXOP_RES_VALUE,
243
			    exop_value->bv_val ? exop_value->bv_val : "",
244
			    exop_value->bv_len );
245
		}
246
	}
247
	return rc;
248
}
249
250
static int
251
check_and_send_SASL_response(Slapi_PBlock *pb, ber_tag_t tag, BerElement *ber, Connection *conn)
252
{
253
	/*
254
	 * if this is an LDAPv3 BindResponse, check to see if the
255
	 * optional serverSaslCreds OCTET STRING is present and needs
256
	 * to be appended.
257
	 */
258
	int rc= 0;
259
	if ( LDAP_RES_BIND == tag && conn->c_ldapversion >= LDAP_VERSION3 )
260
	{
261
		struct berval *bind_ret_saslcreds; /* v3 serverSaslCreds */
262
		slapi_pblock_get(pb, SLAPI_BIND_RET_SASLCREDS, &bind_ret_saslcreds);
263
		if ( bind_ret_saslcreds != NULL ) {
264
			rc = ber_printf( ber, "to",
265
			    LDAP_TAG_SASL_RES_CREDS,
266
			    bind_ret_saslcreds->bv_val ? bind_ret_saslcreds->bv_val : "",
267
			    bind_ret_saslcreds->bv_len );
268
		}
269
	}
270
	return rc;
271
}
272
273
274
/*
275
 * the input ber, if present, is not consumed
276
 */
277
void
278
send_ldap_result_ext(
279
    Slapi_PBlock	*pb,
280
    int			err,
281
    char		*matched,
282
    char		*text,
283
    int			nentries,
284
    struct berval	**urls,
285
    BerElement          *ber
286
)
287
{
288
	Connection	*conn = pb->pb_conn;
289
	int		i, rc, logit = 0;
290
	ber_tag_t	tag;
291
	int             flush_ber_element = 1;
292
	Slapi_Operation *operation;
293
	const char *dn = NULL;
294
	Slapi_DN *sdn = NULL;
295
	int internal_op;
296
	passwdPolicy *pwpolicy = NULL;
297
	
298
	slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
299
0.1.1 by Krzysztof Klimonda
Import upstream version 1.2.11.7
300
	if (operation->o_status == SLAPI_OP_STATUS_RESULT_SENT) {
301
		return; /* result already sent */
302
	}
303
1 by Timo Aaltonen
Import upstream version 1.2.10.2
304
	if ( ber != NULL ) {
305
	    flush_ber_element = 0;
306
	}
307
308
	if(err != LDAP_SUCCESS){
309
		/* count the error for snmp */
310
		/* first check for security errors */
311
                if(   err == LDAP_INVALID_CREDENTIALS
312
                   || err == LDAP_INAPPROPRIATE_AUTH
313
                   || err == LDAP_AUTH_METHOD_NOT_SUPPORTED
314
                   || err == LDAP_STRONG_AUTH_NOT_SUPPORTED
315
                   || err == LDAP_STRONG_AUTH_REQUIRED
316
                   || err == LDAP_CONFIDENTIALITY_REQUIRED
317
                   || err == LDAP_INSUFFICIENT_ACCESS
318
                   || err == LDAP_AUTH_UNKNOWN )
319
		{
320
			slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors);	
321
		}else if(   err != LDAP_REFERRAL 
322
			 && err != LDAP_OPT_REFERRALS
323
			 && err != LDAP_PARTIAL_RESULTS)
324
                {
325
		      /*madman man spec says not to count as normal errors
326
			    --security errors
327
			    --referrals 
328
			    -- partially seviced operations will not be conted as an error
329
                      */
330
			slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsErrors);	
331
		}
332
333
	}
334
335
	LDAPDebug( LDAP_DEBUG_TRACE, "=> send_ldap_result %d:%s:%s\n", err,
336
	    matched ? matched : "", text ? text : "" );
337
338
	switch ( operation->o_tag ) {
339
	case LBER_DEFAULT:
340
		tag = LBER_SEQUENCE;
341
		break;
342
343
	case LDAP_REQ_SEARCH:
344
		tag = LDAP_RES_SEARCH_RESULT;
345
		break;
346
347
	case LDAP_REQ_DELETE:
348
		tag = LDAP_RES_DELETE;
349
		break;
350
351
	case LDAP_REFERRAL:
352
		if ( conn->c_ldapversion > LDAP_VERSION2 ) {
353
			tag = LDAP_TAG_REFERRAL;
354
                        break;
355
		}
356
                /* fallthru */
357
358
	default:
359
		tag = operation->o_tag + 1;
360
		break;
361
	}
362
363
	internal_op = operation_is_flag_set( operation, OP_FLAG_INTERNAL );
364
	if ( ( conn == NULL ) || ( internal_op ) ) {
365
		if ( operation->o_result_handler != NULL ) {
366
			operation->o_result_handler( conn, operation, err,
367
			    matched, text, nentries, urls );
368
			logit = 1;
369
		}
370
		goto log_and_return;
371
	}
372
373
	/* invalid password.  Update the password retry here */
374
	/* put this here for now.  It could be a send_result pre-op plugin. */
375
	if (err == LDAP_INVALID_CREDENTIALS) {
376
		slapi_pblock_get( pb, SLAPI_TARGET_SDN, &sdn );
377
		dn = slapi_sdn_get_dn(sdn);
378
		pwpolicy = new_passwdPolicy(pb, dn);
379
		if (pwpolicy && (pwpolicy->pw_lockout == 1)) {
0.1.1 by Krzysztof Klimonda
Import upstream version 1.2.11.7
380
			if(update_pw_retry( pb ) == LDAP_CONSTRAINT_VIOLATION && !pwpolicy->pw_is_legacy){
381
				/*
382
				 * If we are not using the legacy pw policy behavior,
383
				 * convert the error 49 to 19 (constraint violation)
384
				 * and log a message
385
				 */
386
				err = LDAP_CONSTRAINT_VIOLATION;
387
				text = "Invalid credentials, you now have exceeded the password retry limit.";
388
			}
1 by Timo Aaltonen
Import upstream version 1.2.10.2
389
		}
390
	}
391
        
392
	if ( ber == NULL ) {
393
	    if ( (ber = der_alloc()) == NULL ) {
394
	        LDAPDebug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
395
			goto log_and_return;
396
	    }
397
	}
398
399
	/* there is no admin limit exceeded in v2 - change to size limit XXX */
400
	if ( err == LDAP_ADMINLIMIT_EXCEEDED &&
401
	    conn->c_ldapversion < LDAP_VERSION3 ) {
402
		err = LDAP_SIZELIMIT_EXCEEDED;
403
	}
404
405
	if ( conn->c_ldapversion < LDAP_VERSION3 || urls == NULL ) {
406
		char	*save, *buf = NULL;
407
408
		/*
409
		 * if there are v2 referrals to send, construct
410
		 * the v2 referral string.
411
		 */
412
		if ( urls != NULL ) {
413
			int	len;
414
415
		        /* count the referral */
416
  		        slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
417
418
			/*
419
			 * figure out how much space we need
420
			 */
421
			len = 10; /* strlen("Referral:") + NULL */
422
			for ( i = 0; urls[i] != NULL; i++ ) {
423
				len += urls[i]->bv_len + 1; /* newline + ref */
424
			}
425
			if ( text != NULL ) {
426
				len += strlen( text ) + 1; /* text + newline */
427
			}
428
			/*
429
			 * allocate buffer and fill it in with the error
430
			 * message plus v2-style referrals.
431
			 */
432
			buf = slapi_ch_malloc( len );
433
			*buf = '\0';
434
			if ( text != NULL ) {
435
				strcpy( buf, text );
436
				strcat( buf, "\n" );
437
			}
438
			strcat( buf, "Referral:" );
439
			for ( i = 0; urls[i] != NULL; i++ ) {
440
				strcat( buf, "\n" );
441
				strcat( buf, urls[i]->bv_val );
442
			}
443
			save = text;
444
			text = buf;
445
		}
446
447
		if ( (conn->c_ldapversion < LDAP_VERSION3 &&
448
		    err == LDAP_REFERRAL) || urls != NULL ) {
449
			err = LDAP_PARTIAL_RESULTS;
450
		}
451
		rc = ber_printf( ber, "{it{ess", operation->o_msgid, tag, err,
452
		    matched ? matched : "", text ? text : "" );
453
454
		/*
455
		 * if this is an LDAPv3 ExtendedResponse to an ExtendedRequest,
456
		 * check to see if the optional responseName and response OCTET
457
		 * STRING need to be appended.
458
		 */
459
		if ( rc != LBER_ERROR )
460
		{
461
			rc= check_and_send_extended_result(pb, tag, ber);
462
		}
463
464
		/*
465
		 * if this is an LDAPv3 BindResponse, check to see if the
466
		 * optional serverSaslCreds OCTET STRING is present and needs
467
		 * to be appended.
468
		 */
469
		if ( rc != LBER_ERROR )
470
		{
471
			rc= check_and_send_SASL_response(pb, tag, ber, conn);
472
/* XXXmcs: should we also check for a missing auth response control? */
473
		}
474
475
		if ( rc != LBER_ERROR ) {
476
			rc = ber_printf( ber, "}" ); /* one more } to come */
477
		}
478
479
		if ( buf != NULL ) {
480
			text = save;
481
			slapi_ch_free( (void**)&buf );
482
		}
483
	} else {
484
		/*
485
		 * there are v3 referrals to add to the result
486
		 */
487
	        /* count the referral */
488
		if (! config_check_referral_mode())
489
		    slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
490
		rc = ber_printf( ber, "{it{esst{s", operation->o_msgid, tag, err,
491
		    matched ? matched : "", text ? text : "", LDAP_TAG_REFERRAL,
492
		    urls[0]->bv_val );
493
		for ( i = 1 ; urls[i] != NULL && rc != LBER_ERROR; i++ ) {
494
			rc = ber_printf( ber, "s", urls[i]->bv_val );
495
		}
496
		if ( rc != LBER_ERROR ) {
497
			rc = ber_printf( ber, "}" ); /* two more } to come */
498
		}
499
500
		/*
501
		 * if this is an LDAPv3 ExtendedResponse to an ExtendedRequest,
502
		 * check to see if the optional responseName and response OCTET
503
		 * STRING need to be appended.
504
		 */
505
		if ( rc != LBER_ERROR )
506
		{
507
			rc= check_and_send_extended_result(pb, tag, ber);
508
		}
509
510
		/*
511
		 * if this is an LDAPv3 BindResponse, check to see if the
512
		 * optional serverSaslCreds OCTET STRING is present and needs
513
		 * to be appended.
514
		 */
515
		if ( rc != LBER_ERROR )
516
		{
517
			rc= check_and_send_SASL_response(pb, tag, ber, conn);
518
		}
519
520
		if ( rc != LBER_ERROR ) {
521
			rc = ber_printf( ber, "}" ); /* one more } to come */
522
		}
523
	}
524
	if ( operation->o_results.result_controls != NULL 
525
	    && conn->c_ldapversion >= LDAP_VERSION3
526
	    && write_controls( ber, operation->o_results.result_controls ) != 0 ) {
527
		rc = (int)LBER_ERROR;
528
	}
529
530
	if ( rc != LBER_ERROR ) {	/* end the LDAPMessage sequence */
531
		rc = ber_put_seq( ber );
532
	}
533
534
	if ( rc == LBER_ERROR ) {
535
		LDAPDebug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
536
                if (flush_ber_element == 1) {
537
                    /* we alloced the ber */
538
                    ber_free( ber, 1 /* freebuf */ );
539
                }
540
		goto log_and_return;
541
	}
542
543
	if ( flush_ber_element ) {
544
		/* write only one pdu at a time - wait til it's our turn */
545
		if ( flush_ber( pb, conn, operation, ber, _LDAP_SEND_RESULT ) == 0 ) {
546
			logit = 1;
547
		}
548
	}
549
550
log_and_return:
551
	operation->o_status = SLAPI_OP_STATUS_RESULT_SENT;	/* in case this has not yet been set */
552
553
	if ( logit && operation_is_flag_set( operation,
554
	    OP_FLAG_ACTION_LOG_ACCESS )) {
555
		log_result( pb, operation, err, tag, nentries );
556
	}
557
558
	LDAPDebug( LDAP_DEBUG_TRACE, "<= send_ldap_result\n", 0, 0, 0 );
559
}
560
561
562
void
563
send_nobackend_ldap_result( Slapi_PBlock *pb )
564
{
565
	struct berval	**refurls;
566
	int err;
567
568
	refurls = g_get_default_referral();
569
	err = ( refurls == NULL ) ? LDAP_NO_SUCH_OBJECT : LDAP_REFERRAL;
570
	/* richm 20010831 - bug 556992 - the post op code needs to know what the
571
	   ldap error sent to the client was - slapi_send_ldap_result sets the
572
	   err in the pblock, so this function needs to also */
573
	slapi_pblock_set(pb, SLAPI_RESULT_CODE, &err);
574
575
	slapi_send_ldap_result( pb, err, NULL, NULL, 0, refurls );
576
}
577
578
579
int
580
send_ldapv3_referral(
581
    Slapi_PBlock		*pb,
582
    struct berval	**urls
583
)
584
{
585
	Connection	*conn = pb->pb_conn;
586
	BerElement	*ber;
587
	int		i, rc, logit = 0;
588
	Slapi_Operation *operation;
589
590
	slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
591
592
	LDAPDebug( LDAP_DEBUG_TRACE, "=> send_ldapv3_referral\n", 0, 0, 0 );
593
	
594
	if ( conn == NULL ) {
595
		if ( operation->o_search_referral_handler != NULL ) {
596
			if (( rc = (*operation->o_search_referral_handler)(
597
			    pb->pb_backend, conn, operation, urls )) == 0 ) {
598
				logit = 1;
599
			}
600
			goto log_and_return;
601
		}
602
		return( 0 );
603
	}
604
	if ( urls == NULL ) {
605
		return( 0 );
606
	}
607
608
	if ( (ber = der_alloc()) == NULL ) {
609
		LDAPDebug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
610
		send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,
611
		    "ber_alloc", 0, NULL );
612
		return( -1 );
613
	}
614
615
	/*
616
	 * send the ldapv3 SearchResultReference. it looks like this:
617
	 *
618
	 *	SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL
619
	 *
620
	 * all wrapped up in an LDAPMessage sequence which looks like this:
621
	 *	LDAPMessage ::= SEQUENCE {
622
	 *		messageID       MessageID,
623
	 *		SearchResultReference
624
	 *		controls        [0] Controls OPTIONAL
625
	 *      }
626
	 */
627
628
	for ( i = 0, rc = ber_printf( ber, "{it{", operation->o_msgid,
629
	    LDAP_RES_SEARCH_REFERENCE );
630
	    rc != LBER_ERROR && urls[i] != NULL; i++ ) {
631
		rc = ber_printf( ber, "s", urls[i]->bv_val );
632
	}
633
	if ( rc == LBER_ERROR ) {
634
		LDAPDebug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
635
		send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,
636
		    "ber_printf", 0, NULL );
637
		return( -1 );
638
	}
639
	if ( ber_printf( ber, "}}" ) == LBER_ERROR ) {
640
		LDAPDebug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
641
		send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,
642
		    "ber_printf", 0, NULL );
643
		return( -1 );
644
	}
645
646
	/* write only one pdu at a time - wait til it's our turn */
647
	if ( (rc = flush_ber( pb, conn, operation, ber, _LDAP_SEND_REFERRAL
648
	    )) == 0 ) {
649
		logit = 1;
650
	}
651
652
log_and_return:
653
	if ( logit && operation_is_flag_set( operation,
654
	    OP_FLAG_ACTION_LOG_ACCESS)){
655
		log_referral( operation );
656
	}
657
658
	return( rc );
659
}
660
    
661
/*
662
 * send_ldap_referral - called to send a referral (SearchResultReference)
663
 * to a v3 client during a search. for v2 clients, it just adds the
664
 * referral(s) to the url list passed in the third parameter. this list
665
 * is then returned to v2 clients when it is passed to send_ldap_result().
666
 */
667
int
668
send_ldap_referral (
669
    Slapi_PBlock		*pb,
670
    Slapi_Entry		*e,
671
    struct berval	**refs,
672
    struct berval	***urls
673
)
674
{
675
	char	*refAttr = "ref";
676
	char	*attrs[2] = { NULL, NULL };
677
678
	/* count the referral */
679
	slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
680
681
	attrs[0] = refAttr;
682
	if ( e != NULL && 
683
	    plugin_call_acl_plugin (pb, e, attrs, NULL, 
684
				    SLAPI_ACL_READ, ACLPLUGIN_ACCESS_DEFAULT, NULL)
685
	    != LDAP_SUCCESS ) {
686
		return( 0 );
687
	}
688
	if ( pb->pb_conn && pb->pb_conn->c_ldapversion > LDAP_VERSION2 ) {
689
		/*
690
		 * v3 connection - send the referral(s) in a
691
		 * SearchResultReference packet right now.
692
		 */
693
		return( send_ldapv3_referral( pb, refs ) );
694
	} else {
695
		/*
696
		 * v2 connection - add the referral(s) to the
697
		 * list being maintained in urls. they will be
698
		 * sent to the client later when send_ldap_result()
699
		 * is called.
700
		 */
701
		int	i, need, have;
702
703
		if ( refs == NULL && urls == NULL ) {
704
		    return( 0 );
705
		}
706
707
		for ( have = 0; *urls != NULL && (*urls)[have] != NULL;
708
		    have++ ) {
709
			;	/* NULL */
710
		}
711
		for ( need = 0; refs != NULL && refs[need] != NULL; need++ ) {
712
			;	/* NULL */
713
		}
714
715
		*urls = (struct berval **) slapi_ch_realloc( (char *) *urls,
716
		    (need + have + 1) * sizeof(struct berval *) );
717
		for ( i = have; i < have + need; i++ ) {
718
			(*urls)[i] = ber_bvdup( refs[i - have] );
719
		}
720
		(*urls)[i] = NULL;
721
	}
722
723
	return( 0 );
724
}
725
726
int
727
encode_attr_2(
728
    Slapi_PBlock		*pb,
729
    BerElement		*ber,
730
    Slapi_Entry		*e,
731
    Slapi_ValueSet		*vs,
732
    int			attrsonly,
733
    const char		*attribute_type,
734
    const char		*returned_type
735
)
736
{
737
738
	char *attrs[2] = { NULL, NULL };
739
	Slapi_Value *v;
740
	int i = slapi_valueset_first_value(vs,&v);
741
742
	if (i==-1)
743
	{
744
		return( 0 );
745
	}
746
747
	attrs[0] = (char*)attribute_type;
748
749
#if !defined(DISABLE_ACL_CHECK)
750
	if ( plugin_call_acl_plugin (pb, e, attrs, NULL, SLAPI_ACL_READ, 
751
				     ACLPLUGIN_ACCESS_READ_ON_ATTR, NULL ) != LDAP_SUCCESS ) {
752
		return( 0 );
753
	}
754
#endif
755
756
	if ( ber_printf( ber, "{s[", returned_type ) == -1 ) {
757
		LDAPDebug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
758
		ber_free( ber, 1 );
759
		send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,
760
		    "ber_printf type", 0, NULL );
761
		return( -1 );
762
	}
763
764
	if ( ! attrsonly )
765
	{
766
		while(i!=-1)
767
		{
768
			if ( ber_printf( ber, "o", v->bv.bv_val,v->bv.bv_len ) == -1 )
769
			{
770
				LDAPDebug( LDAP_DEBUG_ANY,
771
				    "ber_printf failed\n", 0, 0, 0 );
772
				ber_free( ber, 1 );
773
				send_ldap_result( pb, LDAP_OPERATIONS_ERROR,
774
				    NULL, "ber_printf value", 0, NULL );
775
				return( -1 );
776
			}
777
			i= slapi_valueset_next_value(vs,i,&v);
778
		}
779
	}
780
781
	if ( ber_printf( ber, "]}" ) == -1 ) {
782
		LDAPDebug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
783
		ber_free( ber, 1 );
784
		send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,
785
		    "ber_printf type end", 0, NULL );
786
		return( -1 );
787
	}
788
789
	return( 0 );
790
}
791
792
int
793
encode_attr(
794
    Slapi_PBlock		*pb,
795
    BerElement		*ber,
796
    Slapi_Entry		*e,
797
    Slapi_Attr		*a,
798
    int			attrsonly,
799
    char		*type
800
)
801
{
802
	return encode_attr_2(pb,ber,e,&(a->a_present_values),attrsonly,a->a_type,type);
803
}
804
805
#define LASTMODATTR( x )	(strcasecmp( x, "modifytimestamp" ) == 0 \
806
				    || strcasecmp( x, "modifiersname" ) == 0 \
807
				    || strcasecmp( x, "createtimestamp" ) == 0 \
808
				    || strcasecmp( x, "creatorsname" ) == 0)
809
810
/*
811
 * send_ldap_search_entry:
812
 * return 0 if OK
813
 * return 1 if this entry not sent
814
 * return -1 if error result sent or fatal error
815
 */
816
int
817
send_ldap_search_entry(
818
    Slapi_PBlock		*pb,
819
    Slapi_Entry		*e,
820
    LDAPControl		**ectrls,
821
    char		**attrs,
822
    int			attrsonly
823
)
824
{
825
    return send_ldap_search_entry_ext(pb, e, ectrls, attrs, attrsonly, 0, 0, NULL);
826
}
827
828
/*
829
 * LDAPv2 attr names from RFC1274 and their LDAPv3 equivalent.
830
 *
831
 * The ;binary attrs are deliberately reversed.
832
 */
833
static const char *idds_v2_attrt[][2] = {
834
  {"commonName","cn"},
835
  {"surname","sn"},
836
  {"userCertificate;binary","userCertificate"},
837
  {"caCertificate;binary","caCertificate"},
838
  {"countryName","c"},
839
  {"localityName","l"},
840
  {"stateOrProvinceName","st"},
841
  {"streetAddress","street"},
842
  {"organizationName","o"},
843
  {"organizationalUnitName","ou"},
844
  {"userid","uid"},
845
  {"rfc822Mailbox","mail"},
846
  {"domainComponent","dc"},
847
  {"mobileTelephoneNumber","mobile"},
848
  {"pagerTelephoneNumber","pager"},
849
  {"friendlyCountryName","co"},
850
  {NULL,NULL}
851
};
852
853
/*
854
 * Map an LDAPv3 attribute name to its LDAPv2 equivalent.
855
 */
856
static const char *idds_map_attrt_v3( 
857
  const char *atin
858
)
859
{
860
  int i;
861
862
  for (i = 0; idds_v2_attrt[i][0] != NULL; i++) {
863
    if (strcasecmp(atin, idds_v2_attrt[i][1]) == 0) {
864
      return (idds_v2_attrt[i][0]);
865
    }
866
  }
867
868
  return NULL;
869
}
870
871
/*
872
 * RFC: 2251 Page: 29
873
 *
874
 *  attributes: A list of the attributes to be returned from each entry
875
 *  which matches the search filter. There are two special values which
876
 *  may be used: an empty list with no attributes, and the attribute
877
 *  description string "*".  Both of these signify that all user
878
 *  attributes are to be returned.  (The "*" allows the client to
879
 *  request all user attributes in addition to specific operational
880
 *  attributes).
881
 *
882
 *  Attributes MUST be named at most once in the list, and are returned
883
 *  at most once in an entry.   If there are attribute descriptions in
884
 *  the list which are not recognized, they are ignored by the server.
885
 *
886
 *  If the client does not want any attributes returned, it can specify
887
 *  a list containing only the attribute with OID "1.1".  This OID was
888
 *  chosen arbitrarily and does not correspond to any attribute in use.
889
 */
890
     
891
892
/* Helper functions */
893
894
static int send_all_attrs(Slapi_Entry *e,char **attrs,Slapi_Operation *op,Slapi_PBlock *pb,BerElement *ber,int attrsonly,int ldapversion,int *dontsendattr, int real_attrs_only, int some_named_attrs)
895
{
896
	int i = 0;
897
	int rc = 0;
898
899
	int typelist_flags = 0;
900
	vattr_type_thang *typelist = NULL;
901
	vattr_type_thang *current_type = NULL;
902
	char *current_type_name = NULL;
903
	int rewrite_rfc1274 = 0;
904
	int vattr_flags = 0;
905
906
	if(real_attrs_only == SLAPI_SEND_VATTR_FLAG_REALONLY)
907
		vattr_flags = SLAPI_REALATTRS_ONLY;
908
	else
909
	{
910
		vattr_flags = SLAPI_VIRTUALATTRS_REQUEST_POINTERS;
911
		if(real_attrs_only == SLAPI_SEND_VATTR_FLAG_VIRTUALONLY)
912
			vattr_flags |= SLAPI_VIRTUALATTRS_ONLY;
913
	}
914
915
	if (some_named_attrs) {
916
		/*
917
		 * If the client listed some attribute types by name, one or
918
		 * more of the requested types MAY be operational.  Inform the
919
		 * virtual attributes subsystem (certain optimizations are done
920
		 * by the vattrs code and vattr service providers if operational
921
		 * attributes are NOT requested).
922
		 */
923
		vattr_flags |= SLAPI_VIRTUALATTRS_LIST_OPERATIONAL_ATTRS;
924
	}
925
926
	rc = slapi_vattr_list_attrs(e,&typelist,vattr_flags,&typelist_flags);
927
	if (0 != rc) {
928
		goto exit;
929
	}
930
931
	if (typelist_flags & SLAPI_VIRTUALATTRS_REALATTRS_ONLY) {
932
		/* 
933
		 * There is no point in consulting the vattr service providers
934
                 * for every attr if they didn't contribute to the attr list.
935
		 */
936
		vattr_flags |= SLAPI_REALATTRS_ONLY;
937
	}
938
939
	rewrite_rfc1274 = config_get_rewrite_rfc1274();
940
941
	/* Send the attrs back to the client */
942
	for (current_type = vattr_typethang_first(typelist); current_type; current_type = vattr_typethang_next(current_type) ) {
943
944
		Slapi_ValueSet **values = NULL;
945
		int attr_free_flags = 0;
946
		unsigned long current_type_flags = 0;
947
		int sendit = 0;
948
		char *name_to_return = NULL;
949
		int *type_name_disposition = 0;
950
		char **actual_type_name = NULL;
951
		const char *v2name = NULL;
952
953
		current_type_name = vattr_typethang_get_name(current_type);
954
		current_type_flags = vattr_typethang_get_flags(current_type);
955
956
		name_to_return = current_type_name;
957
		/* We only return operational attributes if the client is LDAPv2 and the attribute is one of a special set,
958
		   OR if the client also requested the attribute by name. If it did, we use the specified name rather than
959
		   the base name.
960
		 */
961
		if ( current_type_flags & SLAPI_ATTR_FLAG_OPATTR ) {
962
			if ( LDAP_VERSION2 == ldapversion && LASTMODATTR( current_type_name) ) {
963
				sendit = 1;
964
			} else {
965
				for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ ) {
966
					if ( slapi_attr_type_cmp( attrs[i], current_type_name, SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) {
967
						sendit = 1;
968
						name_to_return = op->o_searchattrs[i];
969
						break;
970
					}
971
				}
972
			}
973
		/*
974
		 * it's a user attribute. send it.
975
		 */
976
		} else {
977
			sendit = 1;
978
		}
979
		/* Now send to the client */
980
		if (sendit) {
981
			/**********************************************/
982
			int item_count = 0;
983
			int iter = 0;
984
			Slapi_DN *namespace_dn;
985
			Slapi_Backend *backend=0;
986
			vattr_context *ctx;
987
988
			/* get the namespace dn */
989
			slapi_pblock_get( pb, SLAPI_BACKEND, (void *)&backend);
990
			namespace_dn = (Slapi_DN*)slapi_be_getsuffix(backend, 0);
991
992
			/* Get the attribute value from the vattr service */
993
			/* ctx will be freed by attr_context_ungrok() */
994
			ctx = vattr_context_new ( pb );
995
			rc = slapi_vattr_namespace_values_get_sp(
996
					ctx,
997
					e,
998
					namespace_dn,
999
					current_type_name,
1000
					&values,
1001
					&type_name_disposition,
1002
					&actual_type_name,
1003
					vattr_flags | SLAPI_VIRTUALATTRS_SUPPRESS_SUBTYPES,
1004
					&attr_free_flags, 
1005
					&item_count
1006
					);
1007
			if (0 == rc && item_count > 0) {
1008
1009
				for(iter=0; iter<item_count; iter++)
1010
				{
1011
					if ( rc != 0 ) {
1012
						/* we hit an error - we need to free all of the stuff allocated by
1013
						   slapi_vattr_namespace_values_get_sp */
1014
						slapi_vattr_values_free(&(values[iter]), &(actual_type_name[iter]), attr_free_flags);
1015
						continue;
1016
					}
1017
1018
					if (SLAPI_VIRTUALATTRS_TYPE_NAME_MATCHED_SUBTYPE == type_name_disposition[iter]) {
1019
						name_to_return = actual_type_name[iter]; 
1020
					}
1021
1022
					/*
1023
					* The dontsendattr array is used to track whether attributes
1024
					* that were explicitly requested by the client have been
1025
					* returned. Check here to see if the attribute we just
1026
					* arranged to send back was explicitly requested, and if so,
1027
					* set its dontsendattr flag so the send_specific_attrs()
1028
					* function does not return it a second time.
1029
					*/					
1030
					for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ ) {
1031
						if ( !dontsendattr[i] && slapi_attr_type_cmp( current_type_name, attrs[i], SLAPI_TYPE_CMP_SUBTYPE ) == 0 ) {
1032
						/* Client is also asking for an attr which is in '*', zap it. */
1033
							dontsendattr[i]= 1;
1034
						}
1035
					}
1036
1037
					rc = encode_attr_2( pb, ber, e, values[iter], attrsonly, current_type_name, name_to_return );
1038
1039
					if (rewrite_rfc1274 != 0) {
1040
						v2name = idds_map_attrt_v3(current_type_name);
1041
						if (v2name != NULL) {
1042
							/* also return values with RFC1274 attr name */
1043
							rc = encode_attr_2(pb, ber, e, values[iter], 
1044
								   attrsonly, 
1045
								   current_type_name, 
1046
								   v2name);
1047
						}
1048
					}
1049
1050
					slapi_vattr_values_free(&(values[iter]), &(actual_type_name[iter]), attr_free_flags);
1051
				}
1052
1053
				slapi_ch_free((void**)&actual_type_name);
1054
				slapi_ch_free((void**)&type_name_disposition);
1055
				slapi_ch_free((void**)&values);
1056
				if ( rc != 0 ) {
1057
					goto exit;
1058
				}
1059
1060
			} else {
1061
				/* if we got here, then either values is NULL or values contains no elements
1062
				   either way we can free it */
1063
				slapi_ch_free((void**)&values);
1064
				slapi_ch_free((void**)&actual_type_name);
1065
				slapi_ch_free((void**)&type_name_disposition);
1066
				rc = 0;
1067
			}
1068
		}		
1069
	}
1070
exit:
1071
	if (NULL != typelist) {
1072
		slapi_vattr_attrs_free(&typelist,typelist_flags);
1073
	}
1074
	return rc;
1075
}
1076
1077
int send_specific_attrs(Slapi_Entry *e,char **attrs,Slapi_Operation *op,Slapi_PBlock *pb,BerElement *ber,int attrsonly,int ldapversion,int *dontsendattr, int real_attrs_only)
1078
{
1079
	int i,j = 0;
1080
	int rc = 0;
1081
	int vattr_flags = 0;
1082
	vattr_context *ctx;
1083
1084
	if(real_attrs_only == SLAPI_SEND_VATTR_FLAG_REALONLY)
1085
		vattr_flags = SLAPI_REALATTRS_ONLY;
1086
	else
1087
	{
1088
		vattr_flags = SLAPI_VIRTUALATTRS_REQUEST_POINTERS;
1089
		if(real_attrs_only == SLAPI_SEND_VATTR_FLAG_VIRTUALONLY)
1090
			vattr_flags |= SLAPI_VIRTUALATTRS_ONLY;
1091
	}
1092
	
1093
	for ( i = 0; attrs != NULL && attrs[i] != NULL; i++ )
1094
	{
1095
		char *current_type_name = attrs[i];
1096
        if(!dontsendattr[i]) {
1097
			Slapi_ValueSet **values = NULL;
1098
			int attr_free_flags = 0;
1099
			char *name_to_return = NULL;
1100
			char **actual_type_name= NULL;
1101
			int *type_name_disposition = 0;
1102
			int item_count = 0;
1103
			int iter = 0;
1104
			Slapi_DN *namespace_dn;
1105
			Slapi_Backend *backend=0;
1106
1107
    		/*
1108
    		 * Here we call the computed attribute code to see whether
1109
    		 * the requested attribute is to be computed. 
1110
    		 * The subroutine compute_attribute calls encode_attr on our behalf, in order
1111
    		 * to avoid the inefficiency of returning a complex structure
1112
    		 * which we'd have to free
1113
    		 */
1114
    		rc = compute_attribute(attrs[i],pb,ber,e,attrsonly,op->o_searchattrs[i]);
1115
    		if (0 == rc) {
1116
    			continue; /* Means this was a computed attr and we prcessed it OK. */
1117
    		}
1118
    		if (-1 != rc) {
1119
    			/* Means that some error happened */
1120
    			return rc;
1121
    		}
1122
    		else {
1123
    			rc = 0; /* Means that we just didn't recognize this as a computed attr */
1124
    		}
1125
1126
			/* get the namespace dn */
1127
			slapi_pblock_get( pb, SLAPI_BACKEND, (void *)&backend);
1128
			namespace_dn = (Slapi_DN*)slapi_be_getsuffix(backend, 0);
1129
1130
			/* Get the attribute value from the vattr service */
1131
			/* ctx will be freed by attr_context_ungrok() */
1132
			ctx = vattr_context_new ( pb );
1133
			rc = slapi_vattr_namespace_values_get_sp(
1134
					ctx,
1135
					e,
1136
					namespace_dn,
1137
					current_type_name,
1138
					&values,
1139
					&type_name_disposition,
1140
					&actual_type_name,
1141
					vattr_flags,
1142
					&attr_free_flags, 
1143
					&item_count
1144
					);
1145
			if (0 == rc && item_count > 0) {
1146
1147
				for(iter=0; iter<item_count; iter++)
1148
				{
1149
					if ( rc != 0 ) {
1150
						/* we hit an error - we need to free all of the stuff allocated by
1151
						   slapi_vattr_namespace_values_get_sp */
1152
						slapi_vattr_values_free(&(values[iter]), &(actual_type_name[iter]), attr_free_flags);
1153
						continue;
1154
					}
1155
					if (SLAPI_VIRTUALATTRS_TYPE_NAME_MATCHED_SUBTYPE == type_name_disposition[iter]) {
1156
						name_to_return = actual_type_name[iter]; 
1157
					} else {
1158
						name_to_return = op->o_searchattrs[i];
1159
					}
1160
1161
					/*
1162
					 * The client may have specified a list of attributes
1163
					 * with duplicates, 'cn cn cn'.
1164
					 * We need to determine which of any duplicates take precedence
1165
					 * For subtypes, the attribute which is most generic should be
1166
					 * returned (since it will also trigger the return of the less
1167
					 * generic attribute subtypes.
1168
					 */
1169
					for ( j = i+1; attrs[j] != NULL && dontsendattr[i]==0; j++ )
1170
					{
1171
						if ( !dontsendattr[j] && slapi_attr_type_cmp( attrs[j], actual_type_name[iter], SLAPI_TYPE_CMP_SUBTYPE ) == 0 )
1172
						{
1173
							/* discover which is the more generic attribute and cancel the other*/
1174
							int attrbase = slapi_attr_type_cmp( attrs[j], current_type_name, SLAPI_TYPE_CMP_EXACT );
1175
1176
							if(attrbase >= 0)
1177
								dontsendattr[j]= 1;
1178
							else
1179
								dontsendattr[i]= 1; /* the current value is superceeded later */
1180
						}
1181
					}
1182
1183
					/* we may have just cancelled ourselves so check */
1184
					if(!dontsendattr[i])
1185
						rc = encode_attr_2( pb, ber, e, values[iter], attrsonly, current_type_name, name_to_return );
1186
					
1187
					slapi_vattr_values_free(&(values[iter]), &(actual_type_name[iter]), attr_free_flags);
1188
				}
1189
1190
				slapi_ch_free((void**)&actual_type_name);
1191
				slapi_ch_free((void**)&type_name_disposition);
1192
				slapi_ch_free((void**)&values);
1193
				if ( rc != 0 ) {
1194
					goto exit;
1195
				}
1196
1197
			} else {
1198
				/* if we got here, then either values is NULL or values contains no elements
1199
				   either way we can free it */
1200
				slapi_ch_free((void**)&values);
1201
				slapi_ch_free((void**)&actual_type_name);
1202
				slapi_ch_free((void**)&type_name_disposition);
1203
				rc = 0;
1204
			}
1205
        } 	
1206
	}
1207
exit:
1208
	return rc;
1209
1210
}
1211
1212
1213
int
1214
send_ldap_search_entry_ext(
1215
    Slapi_PBlock		*pb,
1216
    Slapi_Entry		*e,
1217
    LDAPControl		**ectrls,
1218
    char		**attrs,
1219
    int			attrsonly,
1220
    int                 send_result,
1221
    int                 nentries,
1222
    struct berval       **urls
1223
)
1224
{
1225
	Connection	*conn = pb->pb_conn;
1226
	Operation	*op = pb->pb_op;
1227
	BerElement	*ber = NULL;
1228
	int		i, rc = 0, logit = 0;
1229
	int		alluserattrs, noattrs, some_named_attrs;
1230
	int *dontsendattr= NULL;
1231
	Slapi_Operation *operation;
1232
	int real_attrs_only = 0;
1233
	LDAPControl		**ctrlp = 0;
1234
	Slapi_Entry *gerentry = NULL;
1235
	Slapi_Entry *ecopy = NULL;
1236
	LDAPControl	**searchctrlp = NULL;
1237
	
1238
1239
	slapi_pblock_get (pb, SLAPI_OPERATION, &operation);
1240
1241
	LDAPDebug( LDAP_DEBUG_TRACE, "=> send_ldap_search_entry (%s)\n",
1242
	    e?slapi_entry_get_dn_const(e):"null", 0, 0 );
1243
1244
	/* set current entry */
1245
	slapi_pblock_set(pb, SLAPI_SEARCH_ENTRY_ORIG, e);
1246
	/* set controls */
1247
	slapi_pblock_set(pb, SLAPI_SEARCH_CTRLS, ectrls);
1248
1249
	/* call pre entry fn */
1250
	rc = plugin_call_plugins(pb, SLAPI_PLUGIN_PRE_ENTRY_FN);
1251
	if (rc) {
1252
		LDAPDebug( LDAP_DEBUG_ANY,
1253
				   "error returned by pre entry plugins for entry %s\n",
1254
				   e?slapi_entry_get_dn_const(e):"null", 0, 0 );
1255
		goto cleanup;
1256
	}
1257
1258
	slapi_pblock_get(pb, SLAPI_SEARCH_ENTRY_COPY, &ecopy);
1259
	if (ecopy) {
1260
		e = ecopy; /* send back the altered entry */
1261
	}
1262
	slapi_pblock_get(pb, SLAPI_SEARCH_CTRLS, &searchctrlp);
1263
1264
	if ( conn == NULL && e ) {
1265
		if ( op->o_search_entry_handler != NULL ) {
1266
			if (( rc = (*op->o_search_entry_handler)(
1267
			    pb->pb_backend, conn, op, e )) == 0 ) {
1268
				logit = 1;
1269
				goto log_and_return;
1270
			} else {
1271
				goto cleanup;
1272
			}
1273
		}
1274
		rc = 0;
1275
		goto cleanup;
1276
	}
1277
1278
#if !defined(DISABLE_ACL_CHECK)
1279
	if ( e && plugin_call_acl_plugin (pb, e, attrs, NULL, 
1280
				    SLAPI_ACL_READ, ACLPLUGIN_ACCESS_READ_ON_ENTRY, NULL ) != LDAP_SUCCESS ) {
1281
		LDAPDebug( LDAP_DEBUG_ACL, "acl: access to entry not allowed\n",
1282
		    0, 0, 0 );
1283
		rc = 1;
1284
		goto cleanup;
1285
	}
1286
#endif
1287
1288
	if (NULL == e) {
1289
		rc = 1;	/* everything is ok - don't send the result */
1290
		goto cleanup;
1291
	}
1292
1293
	if ( (ber = der_alloc()) == NULL ) {
1294
		LDAPDebug( LDAP_DEBUG_ANY, "ber_alloc failed\n", 0, 0, 0 );
1295
		send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,
1296
		    "ber_alloc", 0, NULL );
1297
		rc = -1;
1298
		goto cleanup;
1299
	}
1300
1301
	rc = ber_printf( ber, "{it{s{", op->o_msgid,
1302
	    LDAP_RES_SEARCH_ENTRY, slapi_entry_get_dn_const(e) );
1303
1304
	if ( rc == -1 ) {
1305
		LDAPDebug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1306
		send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,
1307
		    "ber_printf dn", 0, NULL );
1308
		goto cleanup;
1309
	}
1310
1311
	/*
1312
	 * in ldapv3, the special attribute "*" means all user attributes,
1313
	 * NULL means all user attributes, and "1.1" means no attributes.
1314
	 * operational attributes are only retrieved if they are named
1315
	 * specifically.
1316
	 */
1317
1318
	/* figure out if we want all user attributes or no attributes at all */
1319
	alluserattrs = 0;
1320
	noattrs = 0;
1321
	some_named_attrs = 0;
1322
	if ( attrs == NULL ) {
1323
		alluserattrs = 1;
1324
	} else {
1325
		for ( i = 0; attrs[i] != NULL; i++ ) {
1326
			if ( strcmp( LDAP_ALL_USER_ATTRS, attrs[i] ) == 0 ) {
1327
				alluserattrs = 1;
1328
			} else if ( strcmp( LDAP_NO_ATTRS, attrs[i] ) == 0 ) {
1329
				noattrs = 1;
1330
			} else {
1331
				some_named_attrs = 1;
1332
			}
1333
		}
1334
		if ( i > 1 && noattrs ) {
1335
			/*
1336
			 * user has specified the special "1.1" noattrs attr
1337
			 * and some other stuff. this is not allowed, but
1338
			 * what should we do? we'll allow them to keep going.
1339
			 */
1340
			LDAPDebug( LDAP_DEBUG_TRACE,
1341
			    "Accepting illegal other attributes specified with "
1342
			    "special \"1.1\" attribute\n", 0, 0, 0 );
1343
		}
1344
        /*
1345
         * We maintain a flag array so that we can remove requests
1346
         * for duplicate attributes.
1347
         */
1348
    	dontsendattr= (int*) slapi_ch_calloc( i+1, sizeof(int) );
1349
	}
1350
1351
1352
	/* determine whether we are to return virtual attributes */
1353
	slapi_pblock_get(pb, SLAPI_REQCONTROLS, &ctrlp);
1354
	if(slapi_control_present(ctrlp, LDAP_CONTROL_REAL_ATTRS_ONLY, NULL, NULL))
1355
		real_attrs_only = SLAPI_SEND_VATTR_FLAG_REALONLY;
1356
1357
	if(slapi_control_present(ctrlp, LDAP_CONTROL_VIRT_ATTRS_ONLY, NULL, NULL))
1358
	{
1359
		if(real_attrs_only != SLAPI_SEND_VATTR_FLAG_REALONLY)
1360
			real_attrs_only = SLAPI_SEND_VATTR_FLAG_VIRTUALONLY;
1361
		else
1362
		{
1363
			/* we cannot service a request for virtual only and real only */
1364
			send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,
1365
				"Both real and virtual attributes only controls", 0, NULL );
1366
			rc = -1;
1367
			goto cleanup;
1368
		}
1369
	}
1370
1371
	/* look through each attribute in the entry */
1372
	if ( alluserattrs ) {
1373
		rc = send_all_attrs(e,attrs,op,pb,ber,attrsonly,conn->c_ldapversion,dontsendattr, real_attrs_only, some_named_attrs);
1374
	}
1375
	
1376
	/* if the client explicitly specified a list of attributes look through each attribute requested */
1377
	if( (rc == 0) && (attrs!=NULL)) {
1378
		rc = send_specific_attrs(e,attrs,op,pb,ber,attrsonly,conn->c_ldapversion,dontsendattr,real_attrs_only);
1379
	}
1380
1381
	/* Append effective rights to the stream of attribute list */
1382
	if ( operation->o_flags & OP_FLAG_GET_EFFECTIVE_RIGHTS )
1383
	{
1384
		char *gerstr;
1385
		char *entryrights;
1386
		char *attributerights;
1387
		char *p;
1388
1389
		slapi_pblock_get (pb, SLAPI_PB_RESULT_TEXT, &gerstr);
1390
1391
		/* Syntax check - see acleffectiverights.c */
1392
		if (gerstr && (p = strchr(gerstr, '\n')) != NULL &&
1393
		    strncasecmp (gerstr, "entryLevelRights: ",
1394
				 strlen("entryLevelRights: ")) == 0 &&
1395
		    strncasecmp (p+1, "attributeLevelRights: ",
1396
				 strlen("attributeLevelRights: ")) == 0 )
1397
		{
1398
			entryrights = gerstr + strlen ("entryLevelRights: ");
1399
			*p = '\0';
1400
			attributerights = p + 1 + strlen ("attributeLevelRights: ");
1401
			ber_printf( ber, "{s[o]}", "entryLevelRights", entryrights, strlen(entryrights) );
1402
			ber_printf( ber, "{s[o]}", "attributeLevelRights", attributerights, strlen(attributerights) );
1403
		}
1404
	}
1405
1406
	if (rc != 0) {
1407
		goto cleanup;
1408
	}
1409
1410
	rc = ber_printf( ber, "}}" );
1411
1412
	if ( conn->c_ldapversion >= LDAP_VERSION3 ) {
1413
		if ( searchctrlp != NULL ) {
1414
			rc = write_controls( ber, searchctrlp );
1415
		}
1416
	}
1417
1418
	if ( rc != -1 ) {
1419
		rc = ber_printf( ber, "}" );
1420
	}
1421
1422
	if ( rc == -1 ) {
1423
		LDAPDebug( LDAP_DEBUG_ANY, "ber_printf failed\n", 0, 0, 0 );
1424
		send_ldap_result( pb, LDAP_OPERATIONS_ERROR, NULL,
1425
		    "ber_printf entry end", 0, NULL );
1426
		goto cleanup;
1427
	}
1428
1429
	if (send_result) {
1430
	    send_ldap_result_ext( pb, LDAP_SUCCESS, NULL, NULL, nentries, urls, ber);
1431
	}
1432
1433
	/* write only one pdu at a time - wait til it's our turn */
1434
	if ( (rc = flush_ber( pb, conn, op, ber, _LDAP_SEND_ENTRY )) == 0 ) {
1435
		logit = 1;
1436
	}
1437
	ber = NULL; /* flush_ber will always free the ber */
1438
1439
log_and_return:
0.1.1 by Krzysztof Klimonda
Import upstream version 1.2.11.7
1440
	if ( logit && operation_is_flag_set(operation, OP_FLAG_ACTION_LOG_ACCESS)) {
1 by Timo Aaltonen
Import upstream version 1.2.10.2
1441
1442
	    log_entry( op, e );
1443
1444
	    if (send_result) {
1445
		ber_tag_t	tag;
1446
1447
		switch ( op->o_tag ) {
1448
		case LBER_DEFAULT:
1449
		    tag = LBER_SEQUENCE;
1450
		    break;
1451
1452
		case LDAP_REQ_SEARCH:
1453
		    tag = LDAP_RES_SEARCH_RESULT;
1454
		    break;
1455
1456
		case LDAP_REQ_DELETE:
1457
		    tag = LDAP_RES_DELETE;
1458
		    break;
1459
1460
		case LDAP_REFERRAL:
1461
		    if ( conn != NULL && conn->c_ldapversion > LDAP_VERSION2 ) {
1462
			tag = LDAP_TAG_REFERRAL;
1463
			break;
1464
		    }
1465
		    /* fallthru */
1466
1467
		default:
1468
		    tag = op->o_tag + 1;
1469
		    break;
1470
		}	    
1471
1472
		log_result( pb, op, LDAP_SUCCESS, tag, nentries );
1473
	    }
1474
	}
1475
cleanup:
1476
	slapi_entry_free(gerentry);
1477
	slapi_pblock_get(pb, SLAPI_SEARCH_ENTRY_COPY, &ecopy);
1478
	slapi_pblock_set(pb, SLAPI_SEARCH_ENTRY_COPY, NULL);
1479
	slapi_entry_free(ecopy);
1480
	slapi_pblock_get(pb, SLAPI_SEARCH_CTRLS, &searchctrlp);
1481
	slapi_pblock_set(pb, SLAPI_SEARCH_CTRLS, NULL);
1482
	if (searchctrlp != ectrls) {
1483
		ldap_controls_free(searchctrlp);
1484
	}
1485
	ber_free( ber, 1 );
1486
	slapi_ch_free( (void **) &dontsendattr );
1487
	LDAPDebug( LDAP_DEBUG_TRACE, "<= send_ldap_search_entry\n", 0, 0, 0 );
1488
1489
	return( rc );
1490
}
1491
1492
1493
1494
1495
/*
1496
 * always frees the ber
1497
 */
1498
static int
1499
flush_ber(
1500
    Slapi_PBlock	*pb,
1501
    Connection	*conn,
1502
    Operation	*op,
1503
    BerElement	*ber,
1504
    int		type
1505
)
1506
{
1507
	ber_len_t	bytes;
1508
	int		rc = 0;
1509
1510
	switch ( type ) {
1511
	case _LDAP_SEND_RESULT:
1512
		rc = plugin_call_plugins( pb, SLAPI_PLUGIN_PRE_RESULT_FN );
1513
		break;
1514
	case _LDAP_SEND_REFERRAL:
1515
		rc = plugin_call_plugins( pb, SLAPI_PLUGIN_PRE_REFERRAL_FN );
1516
		break;
1517
	}
1518
1519
	if ( rc != 0 ) {
1520
		ber_free( ber, 1 );
1521
		return( rc );
1522
	}
1523
1524
	if ((conn->c_flags & CONN_FLAG_CLOSING) || slapi_op_abandoned(pb)) {
1525
	    LDAPDebug(LDAP_DEBUG_CONNS, "ber_flush skipped because the "
1526
		      "connection was marked to be closed or abandoned\n", 0, 0, 0);
1527
			ber_free( ber, 1 );
1528
			/* One of the failure can be because the client has reset the connection ( closed )
1529
			 * and the status needs to be updated to reflect it */
1530
			op->o_status = SLAPI_OP_STATUS_ABANDONED;
1531
			rc = -1;
1532
	} else {
1533
		ber_get_option( ber, LBER_OPT_BYTES_TO_WRITE, &bytes );
1534
1535
		PR_Lock( conn->c_pdumutex );
1536
		rc = ber_flush( conn->c_sb, ber, 1 );
1537
		PR_Unlock( conn->c_pdumutex );
1538
1539
		if ( rc != 0 ) {
1540
			int oserr = errno;
1541
			/* One of the failure can be because the client has reset the connection ( closed )
1542
			 * and the status needs to be updated to reflect it */
1543
			op->o_status = SLAPI_OP_STATUS_ABANDONED;
1544
			
1545
			LDAPDebug( LDAP_DEBUG_CONNS,
1546
				"ber_flush failed, error %d (%s)\n",
1547
				oserr, slapd_system_strerror( oserr ), 0 );
1548
			if (op->o_flags & OP_FLAG_PS) {
1549
			/* We need to tell disconnect_server() not to ding
1550
			* all the psearches if one if them disconnected
1551
			* But we do need to terminate all persistent searches that are using
1552
			* this connection
1553
			*	op->o_flags |= OP_FLAG_PS_SEND_FAILED;
1554
			*/
1555
			}
1556
			do_disconnect_server( conn, op->o_connid, op->o_opid );   
1557
			ber_free( ber, 1 );
1558
		} else {
1559
			PRUint64 b;
1560
			LDAPDebug( LDAP_DEBUG_BER,
1561
				"flush_ber() wrote %u bytes to socket %d\n",
1562
				bytes, conn->c_sd, 0 );
1563
			LL_I2L ( b, bytes ) ;
1564
			slapi_counter_add(num_bytes_sent, b);
1565
			
1566
			if ( type == _LDAP_SEND_ENTRY ) {
1567
				slapi_counter_increment(num_entries_sent);
1568
			}
1569
			if (! config_check_referral_mode())
1570
				slapi_counter_add(g_get_global_snmp_vars()->ops_tbl.dsBytesSent, bytes);
1571
		}
1572
	}
1573
	
1574
	switch ( type ) {
1575
	case _LDAP_SEND_RESULT:
1576
		plugin_call_plugins( pb, SLAPI_PLUGIN_POST_RESULT_FN );
1577
		break;
1578
	case _LDAP_SEND_REFERRAL:
1579
		slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned);
1580
		plugin_call_plugins( pb, SLAPI_PLUGIN_POST_REFERRAL_FN );
1581
		break;
1582
	case _LDAP_SEND_ENTRY:
1583
		slapi_counter_increment(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned);
1584
		plugin_call_plugins( pb, SLAPI_PLUGIN_POST_ENTRY_FN );
1585
		break;
1586
	}
1587
1588
	return( rc );
1589
}
1590
1591
/*
1592
	Puts the default result handlers into the pblock.
1593
	This routine is called before any server call to a
1594
	database backend. 
1595
	Returns : 0 on success, -1 on failure.
1596
*/
1597
int set_db_default_result_handlers(Slapi_PBlock *pb)
1598
{
1599
	int rc = -1;
1600
	if (0 != pb)
1601
	{
1602
		rc = slapi_pblock_set( pb, SLAPI_PLUGIN_DB_ENTRY_FN, 
1603
			(void *) send_ldap_search_entry );
1604
		rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_RESULT_FN, 
1605
	    		(void *) send_ldap_result );
1606
		rc |= slapi_pblock_set( pb, SLAPI_PLUGIN_DB_REFERRAL_FN, 
1607
	    		(void *) send_ldap_referral );
1608
	}
1609
	return rc;
1610
}
1611
1612
1613
struct slapi_note_map {
1614
	unsigned int	snp_noteid;
1615
	char		*snp_string;
1616
};
1617
1618
static struct slapi_note_map notemap[] = {
1619
	{ SLAPI_OP_NOTE_UNINDEXED,   "U" },
1620
	{ SLAPI_OP_NOTE_SIMPLEPAGED, "P" }
1621
};
1622
1623
#define SLAPI_NOTEMAP_COUNT  ( sizeof(notemap) / sizeof(struct slapi_note_map))
1624
1625
1626
/*
1627
 * fill buf with a string representation of the bits present in notes.
1628
 *
1629
 * each bit is mapped to a character string (see table above).
1630
 * the result looks like "notes=U,Z" or similar.
1631
 * if no known notes are present, a zero-length string is generated. 
1632
 * if buflen is too small, the output is truncated.
1633
 *
1634
 * Return value: buf itself.
1635
 */
1636
static char *
1637
notes2str( unsigned int notes, char *buf, size_t buflen )
1638
{
1639
	char *p;
1640
	int i;
1641
	size_t len;
1642
1643
	*buf = '\0';
1644
	--buflen;
1645
	if ( buflen < 7 ) {	/* must be room for "notes=X" at least */
1646
		return( buf );
1647
	}
1648
		
1649
	p = buf;
1650
	for ( i = 0; i < SLAPI_NOTEMAP_COUNT; ++i ) {
1651
		if (( notemap[i].snp_noteid & notes ) != 0 ) {
1652
			if ( p > buf && buflen > 0 ) {
1653
				*p++ = ',';
1654
				*p = '\0';
1655
				--buflen;
1656
			} else {
1657
				strcpy( p, "notes=" );
1658
				p += 6;
1659
				buflen -= 6;
1660
			}
1661
			len = strlen( notemap[i].snp_string );
1662
			if ( buflen < len ) {
1663
				break;	/* bail out (result is truncated) */
1664
			}
1665
			memcpy( p, notemap[i].snp_string, len );
1666
			buflen -= len;
1667
			p += len;
1668
			*p ='\0';
1669
		}
1670
	}
1671
1672
	return( buf );
1673
}
1674
1675
1676
#define ETIME_BUFSIZ 16         /* room for 99999999.999999 */
1677
1678
static void
1679
log_result( Slapi_PBlock *pb, Operation *op, int err, ber_tag_t tag,
1680
	int nentries )
1681
{
1682
	char	*notes_str, notes_buf[ 256 ];
1683
	int	internal_op;
1684
	CSN *operationcsn = NULL;
1685
	char csn_str[CSN_STRSIZE + 5];
1686
        char etime[ETIME_BUFSIZ];
1687
1688
	internal_op = operation_is_flag_set( op, OP_FLAG_INTERNAL );
1689
1690
        if ( (config_get_accesslog_level() & LDAP_DEBUG_TIMING) &&
1691
             (op->o_interval != (PRIntervalTime) 0) ) {
1692
            PRIntervalTime delta = PR_IntervalNow() - op->o_interval;
1693
            PR_snprintf(etime, ETIME_BUFSIZ, "%f", 
1694
                        (PRFloat64)delta/PR_TicksPerSecond());
1695
        } else {
1696
            PR_snprintf(etime, ETIME_BUFSIZ, "%ld", current_time() - op->o_time);
1697
        }
1698
1699
	if ( 0 == pb->pb_operation_notes ) {
1700
		notes_str = "";
1701
	} else {
1702
		notes_str = notes_buf;
1703
		*notes_buf = ' ';
1704
		notes2str( pb->pb_operation_notes, notes_buf + 1,
1705
		    sizeof( notes_buf ) - 1 );
1706
	} 
1707
1708
	csn_str[0] = '\0';
1709
	if (config_get_csnlogging() == LDAP_ON)
1710
	{
1711
		operationcsn = operation_get_csn(op);
1712
		if (NULL != operationcsn)
1713
		{
1714
			char tmp_csn_str[CSN_STRSIZE];
1715
			sprintf(csn_str, " csn=%s", csn_as_string(operationcsn, PR_FALSE, tmp_csn_str));
1716
		}
1717
	}
1718
1719
        if (op->o_tag == LDAP_REQ_BIND && err == LDAP_SASL_BIND_IN_PROGRESS) {
1720
            /* 
1721
             * Not actually an error. 
1722
             * Make that clear in the log.
1723
             */
1724
			if ( !internal_op )
1725
			{
1726
				slapi_log_access( LDAP_DEBUG_STATS,
1727
								  "conn=%" NSPRIu64 " op=%d RESULT err=%d"
1728
								  " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
1729
								  ", SASL bind in progress\n",
1730
								  op->o_connid, 
1731
								  op->o_opid,
1732
								  err, tag, nentries, 
1733
								  etime, 
1734
								  notes_str, csn_str );
1735
			}
1736
			else
1737
			{
1738
				slapi_log_access( LDAP_DEBUG_ARGS,
1739
								  "conn=%s op=%d RESULT err=%d"
1740
								  " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
1741
								  ", SASL bind in progress\n",
1742
									LOG_INTERNAL_OP_CON_ID,
1743
									LOG_INTERNAL_OP_OP_ID,
1744
								  err, tag, nentries, 
1745
								  etime, 
1746
								  notes_str, csn_str );
1747
			}
1748
        } else if (op->o_tag == LDAP_REQ_BIND && err == LDAP_SUCCESS) {
1749
            char *dn = NULL;
1750
1751
            /* 
1752
             * For methods other than simple, the dn in the bind request
1753
             * may be irrelevant. Log the actual authenticated dn.
1754
             */
1755
            slapi_pblock_get(pb, SLAPI_CONN_DN, &dn);
1756
			if ( !internal_op )
1757
			{
1758
				slapi_log_access( LDAP_DEBUG_STATS,
1759
								  "conn=%" NSPRIu64 " op=%d RESULT err=%d"
1760
								  " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
1761
								  " dn=\"%s\"\n",
1762
								  op->o_connid, 
1763
								  op->o_opid,
1764
								  err, tag, nentries, 
1765
								  etime, 
1766
								  notes_str, csn_str, dn ? dn : "");
1767
			}
1768
			else
1769
			{
1770
				slapi_log_access( LDAP_DEBUG_ARGS,
1771
								  "conn=%s op=%d RESULT err=%d"
1772
								  " tag=%" BERTAG_T " nentries=%d etime=%s%s%s"
1773
								  " dn=\"%s\"\n",
1774
									LOG_INTERNAL_OP_CON_ID,
1775
									LOG_INTERNAL_OP_OP_ID,	
1776
								  err, tag, nentries, 
1777
								  etime, 
1778
								  notes_str, csn_str, dn ? dn : "");
1779
			}
1780
            slapi_ch_free((void**)&dn);
1781
        } else {
1782
			if ( !internal_op )
1783
			{
1784
				slapi_log_access( LDAP_DEBUG_STATS,
1785
								  "conn=%" NSPRIu64 " op=%d RESULT err=%d"
1786
								  " tag=%" BERTAG_T " nentries=%d etime=%s%s%s\n",
1787
								  op->o_connid, 
1788
								  op->o_opid,
1789
								  err, tag, nentries, 
1790
								  etime, 
1791
								  notes_str, csn_str );
1792
			}
1793
			else
1794
			{
1795
				slapi_log_access( LDAP_DEBUG_ARGS,
1796
								  "conn=%s op=%d RESULT err=%d"
1797
								  " tag=%" BERTAG_T " nentries=%d etime=%s%s%s\n",
1798
									LOG_INTERNAL_OP_CON_ID,
1799
									LOG_INTERNAL_OP_OP_ID,
1800
								  err, tag, nentries, 
1801
								  etime, 
1802
								  notes_str, csn_str );
1803
			}
1804
		}
1805
}
1806
1807
1808
static void
1809
log_entry( Operation *op, Slapi_Entry *e )
1810
{
1811
	int	internal_op;
1812
1813
	internal_op = operation_is_flag_set( op, OP_FLAG_INTERNAL );
1814
1815
	if ( !internal_op )
1816
	{
1817
		slapi_log_access( LDAP_DEBUG_STATS2, "conn=%" NSPRIu64 " op=%d ENTRY dn=\"%s\"\n",
1818
			op->o_connid, op->o_opid,
0.1.1 by Krzysztof Klimonda
Import upstream version 1.2.11.7
1819
			slapi_entry_get_dn_const(e));
1 by Timo Aaltonen
Import upstream version 1.2.10.2
1820
	}
1821
	else
1822
	{
1823
		if ( config_get_accesslog_level() & LDAP_DEBUG_STATS2 )
1824
		{
1825
			slapi_log_access( LDAP_DEBUG_ARGS, "conn=%s op=%d ENTRY dn=\"%s\"\n",
1826
				LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID,
0.1.1 by Krzysztof Klimonda
Import upstream version 1.2.11.7
1827
				slapi_entry_get_dn_const(e));
1 by Timo Aaltonen
Import upstream version 1.2.10.2
1828
		}
1829
	}
1830
}
1831
1832
1833
static void
1834
log_referral( Operation *op )
1835
{
1836
	int	internal_op;
1837
1838
	internal_op = operation_is_flag_set( op, OP_FLAG_INTERNAL );
1839
1840
	if ( !internal_op )
1841
	{
1842
		slapi_log_access( LDAP_DEBUG_STATS2, "conn=%" NSPRIu64 " op=%d REFERRAL\n",
1843
			op->o_connid, op->o_opid );
1844
	}
1845
	else
1846
	{
1847
		if ( config_get_accesslog_level() & LDAP_DEBUG_STATS2 )
1848
		{
1849
			slapi_log_access( LDAP_DEBUG_ARGS, "conn=%s op=%d REFERRAL\n",
1850
				LOG_INTERNAL_OP_CON_ID, LOG_INTERNAL_OP_OP_ID );
1851
		}
1852
	}
1853
}