2 * Copyright (c) 1990 Regents of the University of Michigan.
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of Michigan at Ann Arbor. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
17 #include <ac/signal.h>
18 #include <ac/socket.h>
19 #include <ac/string.h>
20 #include <ac/syslog.h>
24 #include <quipu/commonarg.h>
25 #include <quipu/ds_error.h>
26 #include <quipu/dap2.h>
27 #include <quipu/dua.h>
30 #include "../../libraries/liblber/lber-int.h" /* get struct berelement */
38 #include "LDAP-types.h"
39 #if ISODEPACKAGE == IC
40 #include <compat/logger.h>
47 * client_request - called by do_queries() when there is activity on the
48 * client socket. It expects to be able to get an LDAP message from the
49 * client socket, parses the first couple of fields, and then calls
50 * do_request() to handle the request. If do_request() (or something
51 * called by it) returns a response to the client (e.g., in the case of
52 * an error), then client_request() is done. If the request is not
53 * responded to (and needs a response), it is added to the queue of
54 * outstanding requests. It will be responded to later via dsa_response(),
55 * once the DSA operation completes.
68 BerElement ber, *copyofber;
71 #ifdef LDAP_CONNECTIONLESS
72 struct sockaddr_in *sai;
74 Debug( LDAP_DEBUG_TRACE, "client_request%s\n",
75 udp ? " udp" : "", 0, 0 );
78 * Get the ldap message, which is a sequence of message id
80 * and then the actual request choice.
83 ber_init_w_nullc( &ber, 0 );
84 if ( (tag = ber_get_next( clientsb, &len, &ber )) == LBER_DEFAULT ) {
85 Debug( LDAP_DEBUG_ANY, "ber_get_next failed\n", 0, 0, 0 );
89 #ifdef LDAP_CONNECTIONLESS
90 if ( udp && dosyslog ) {
91 sai = (struct sockaddr_in *)ber_pvt_sb_udp_get_src( &clientsb );
92 syslog( LOG_INFO, "UDP request from unknown (%s)",
93 inet_ntoa( sai->sin_addr ) );
98 if ( ldap_debug & LDAP_DEBUG_BER )
99 trace_ber( tag, len, ber.ber_buf, stderr, 1, 1 );
104 * This tag should be a normal SEQUENCE tag. In release 2.0 this
105 * tag is 0x10. In the new stuff this is 0x30. To distinguish
106 * between 3.0 and the "correct" stuff, we look for an extra
107 * sequence tag after the bind tag.
110 Debug( LDAP_DEBUG_ANY, "bound %d\n", bound, 0, 0 );
113 if ( tag == OLD_LDAP_TAG_MESSAGE ) {
114 Debug( LDAP_DEBUG_ANY, "version 2.0 detected\n", 0,
117 syslog( LOG_INFO, "old version 2.0 detected" );
126 tber = ber; /* struct copy */
128 ttag = ber_skip_tag( &tber, &tlen );
129 tber.ber_ptr += tlen;
130 /* bind sequence header */
131 ttag = ber_skip_tag( &tber, &tlen );
132 ttag = ber_peek_tag( &tber, &tlen );
134 Debug( LDAP_DEBUG_ANY, "checking for 3.0 tag 0x%lx\n",
136 if ( ttag == LBER_SEQUENCE ) {
137 Debug( LDAP_DEBUG_ANY, "version 3.0 detected\n",
141 "old version 3.0 detected" );
149 if ( ber_get_int( &ber, &msgid ) != LDAP_TAG_MSGID ) {
150 send_ldap_result( clientsb, LBER_DEFAULT, msgid,
151 LDAP_PROTOCOL_ERROR, NULL, "Not an LDAP message" );
156 #ifdef LDAP_CONNECTIONLESS
160 ber_get_stringa( &ber, &logdn );
161 if ( logdn != NULL ) {
163 syslog( LOG_INFO, "UDP requestor: %s", logdn );
165 Debug( LDAP_DEBUG_ANY, "UDP requestor: %s\n", logdn, 0, 0 );
169 #endif /* LDAP_CONNECTIONLESS */
172 if ( ldap_compat == 30 )
173 tag = ber_skip_tag( &ber, &len );
176 tag = ber_peek_tag( &ber, &len );
177 if ( !udp && bound == 0 && tag != LDAP_REQ_BIND
179 && tag != OLD_LDAP_REQ_BIND
182 send_ldap_result( clientsb, tag, msgid, LDAP_OPERATIONS_ERROR,
183 NULL, "Bind operation must come first" );
188 #ifdef LDAP_CONNECTIONLESS
189 if (udp && tag != LDAP_REQ_SEARCH && tag != LDAP_REQ_ABANDON ) {
190 send_ldap_result( clientsb, tag, msgid, LDAP_OPERATIONS_ERROR,
191 NULL, "Only search is supported over UDP/CLDAP" );
195 sai = (struct sockaddr_in *) ber_pvt_sb_udp_get_src( &clientsb );
197 if ( get_cldap_msg( msgid, tag,
198 (struct sockaddr *)sai ) != NULL ) {
200 * duplicate request: toss this one
202 Debug( LDAP_DEBUG_TRACE,
203 "client_request tossing dup request id %ld from %s\n",
204 msgid, inet_ntoa( sai->sin_addr ), 0 );
211 copyofber = ber_dup( &ber );
213 m = add_msg( msgid, tag, copyofber, dsaconn, udp,
214 #ifdef LDAP_CONNECTIONLESS
215 (struct sockaddr *)sai );
221 * Call the appropriate routine to handle the request. If it
222 * returns a nonzero result, the message requires a response, and
223 * so it's left in the queue of outstanding requests, otherwise
227 if ( do_request( clientsb, m, &ber, &bound ) == 0 ) {
235 * do_request - called when a client makes a request, or when a referral
236 * error is returned. In the latter case, a connection is made to the
237 * referred to DSA, and do_request() is called to retry the operation over
238 * that connection. In the former case, do_request() is called to try
239 * the operation over the default association.
250 int resp_required = 0;
252 Debug( LDAP_DEBUG_TRACE, "do_request\n", 0, 0, 0 );
254 switch ( m->m_msgtype ) {
256 case OLD_LDAP_REQ_BIND:
259 resp_required = do_bind( clientsb, m, ber, bound );
263 case OLD_LDAP_REQ_UNBIND:
266 case LDAP_REQ_UNBIND_30:
268 case LDAP_REQ_UNBIND:
274 case OLD_LDAP_REQ_ADD:
277 resp_required = do_add( clientsb, m, ber );
281 case OLD_LDAP_REQ_DELETE:
284 case LDAP_REQ_DELETE_30:
286 case LDAP_REQ_DELETE:
287 resp_required = do_delete( clientsb, m, ber );
291 case OLD_LDAP_REQ_MODRDN:
293 case LDAP_REQ_MODRDN:
294 resp_required = do_modrdn( clientsb, m, ber );
298 case OLD_LDAP_REQ_MODIFY:
300 case LDAP_REQ_MODIFY:
301 resp_required = do_modify( clientsb, m, ber );
305 case OLD_LDAP_REQ_COMPARE:
307 case LDAP_REQ_COMPARE:
308 resp_required = do_compare( clientsb, m, ber );
312 case OLD_LDAP_REQ_SEARCH:
314 case LDAP_REQ_SEARCH:
315 resp_required = do_search( clientsb, m, ber );
319 case OLD_LDAP_REQ_ABANDON:
322 case LDAP_REQ_ABANDON_30:
324 case LDAP_REQ_ABANDON:
325 resp_required = do_abandon( m->m_conn, ber, m->m_uniqid );
329 Debug( LDAP_DEBUG_ANY, "unknown operation %d\n", m->m_msgtype,
332 send_ldap_msgresult( clientsb, m->m_msgtype, m,
333 LDAP_PROTOCOL_ERROR, NULL, "Unknown request type" );
337 return( resp_required );
341 * initiate_dap_operation - initiate a dap operation, rebinding and retrying
342 * the request if necessary. If the request is successfully initiated, 0 is
343 * returned. Otherwise, an indication of the error is returned.
347 initiate_dap_operation(
354 int i, rc, bound = 0;
355 struct DAPindication di;
357 Debug( LDAP_DEBUG_TRACE, "initiate_dap_operation\n", 0, 0, 0 );
359 if ( m->m_conn->c_ad == -1 && do_bind_real( m->m_conn, &bound,
360 &matched ) != LDAP_SUCCESS )
361 return( LDAP_UNAVAILABLE );
363 for ( i = 0; i < 2; i++ ) {
366 rc = DapCompare( m->m_conn->c_ad, m->m_uniqid,
367 (struct ds_compare_arg *) arg, &di, ROS_ASYNC );
371 rc = DapSearch( m->m_conn->c_ad, m->m_uniqid,
372 (struct ds_search_arg *) arg, &di, ROS_ASYNC );
376 rc = DapAddEntry( m->m_conn->c_ad, m->m_uniqid,
377 (struct ds_addentry_arg *) arg, &di, ROS_ASYNC );
381 rc = DapRemoveEntry( m->m_conn->c_ad, m->m_uniqid,
382 (struct ds_removeentry_arg *) arg, &di, ROS_ASYNC );
386 rc = DapModifyEntry( m->m_conn->c_ad, m->m_uniqid,
387 (struct ds_modifyentry_arg *) arg, &di, ROS_ASYNC );
391 rc = DapRead( m->m_conn->c_ad, m->m_uniqid,
392 (struct ds_read_arg *) arg, &di, ROS_ASYNC );
396 rc = DapModifyRDN( m->m_conn->c_ad, m->m_uniqid,
397 (struct ds_modifyrdn_arg *) arg, &di, ROS_ASYNC );
404 Debug( LDAP_DEBUG_TRACE, "operation initiated %d\n", rc, 0,
411 * the operation was not invoked - try rebinding, then
415 (void) dap_unbind( m->m_conn->c_ad );
417 if ( do_bind_real( m->m_conn, &bound, &matched )
422 m->m_conn->c_ad = -1;
424 return( LDAP_UNAVAILABLE ); /* DSA was unreachable */
435 int read_pdu /* If non-zero, PDU was read from client. 0 == PDU is being written */
439 PS input_ps = NULLPS;
443 Debug( LDAP_DEBUG_TRACE, "trace_ber(tag=%#x, ber=%#lx, len=%d)\n", tag,
444 (unsigned long) ber, len );
446 if ( (buf = (unsigned char *) malloc( len + 6 )) == NULL ) {
447 fprintf( trace_file, "Unable to allocate memory\n" );
456 SAFEMEMCPY( buf + 6, ber, len );
458 SAFEMEMCPY( buf, ber, len );
460 if ( (input_ps = ps_alloc( str_open )) == NULLPS )
461 fprintf( trace_file, "ps_alloc failed\n" );
462 else if ( str_setup( input_ps, (char *)buf, len + 6, 1 ) != OK )
463 fprintf( trace_file, "str_setup\n" );
464 else if ( (pe = ps2pe( input_ps )) == NULLPE ) {
465 fprintf(trace_file, "ps2pe: %s\n",
466 ps_error( input_ps->ps_errno ) );
467 lber_bprint( (char *) buf, len + 6 );
472 "-", NULLCP, NULLCP, LLOG_PDUS,
473 LLOG_NONE, -1, 0, NOTOK
475 struct type_LDAP_LDAPMessage *ldap_msg = NULL;
477 if ( decode_LDAP_LDAPMessage(pe, 1, 0, NULL, &ldap_msg)
481 "Error decoding LDAPMessage:\n [%s]\n",
483 fprintf( trace_file, "Here is the PDU:\n" );
484 vsetfp( trace_file, NULL );
487 if (log.ll_events & LLOG_PDUS) {
488 pvpdu (&log, print_LDAP_LDAPMessage_P, pe,
490 "<Bad LDAPMessage>" : "<LDAPMessage>",
494 PLOGP(&log, LDAP_LDAPMessage, pe, failed ? "<Bad LDAPMessage>" : "<LDAPMessage>", read_pdu);
497 free_LDAP_LDAPMessage(ldap_msg);
499 vsetfp( trace_file, NULL );