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; }
int ldap_send_server_request( LDAP *ld, BerElement *ber, ber_int_t msgid, LDAPRequest *parentreq, LDAPURLDesc **srvlist, LDAPConn *lc, LDAPreqinfo *bind, int m_noconn, int m_res ) { LDAPRequest *lr; int incparent, rc; LDAP_ASSERT_MUTEX_OWNER( &ld->ld_req_mutex ); Debug( LDAP_DEBUG_TRACE, "ldap_send_server_request\n", 0, 0, 0 ); incparent = 0; ld->ld_errno = LDAP_SUCCESS; /* optimistic */ LDAP_CONN_LOCK_IF(m_noconn); if ( lc == NULL ) { if ( srvlist == NULL ) { lc = ld->ld_defconn; } else { lc = find_connection( ld, *srvlist, 1 ); if ( lc == NULL ) { if ( (bind != NULL) && (parentreq != NULL) ) { /* Remember the bind in the parent */ incparent = 1; ++parentreq->lr_outrefcnt; } lc = ldap_new_connection( ld, srvlist, 0, 1, bind, 1, m_res ); } } } /* async connect... */ if ( lc != NULL && lc->lconn_status == LDAP_CONNST_CONNECTING ) { ber_socket_t sd = AC_SOCKET_ERROR; struct timeval tv = { 0 }; ber_sockbuf_ctrl( lc->lconn_sb, LBER_SB_OPT_GET_FD, &sd ); /* poll ... */ switch ( ldap_int_poll( ld, sd, &tv, 1 ) ) { case 0: /* go on! */ lc->lconn_status = LDAP_CONNST_CONNECTED; break; case -2: /* async only occurs if a network timeout is set */ /* honor network timeout */ LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex ); if ( time( NULL ) - lc->lconn_created <= ld->ld_options.ldo_tm_net.tv_sec ) { /* caller will have to call again */ ld->ld_errno = LDAP_X_CONNECTING; } LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex ); /* fallthru */ default: /* error */ break; } } if ( lc == NULL || lc->lconn_status != LDAP_CONNST_CONNECTED ) { if ( ld->ld_errno == LDAP_SUCCESS ) { ld->ld_errno = LDAP_SERVER_DOWN; } ber_free( ber, 1 ); if ( incparent ) { /* Forget about the bind */ --parentreq->lr_outrefcnt; } LDAP_CONN_UNLOCK_IF(m_noconn); return( -1 ); } use_connection( ld, lc ); #ifdef LDAP_CONNECTIONLESS if ( LDAP_IS_UDP( ld )) { BerElement tmpber = *ber; ber_rewind( &tmpber ); LDAP_MUTEX_LOCK( &ld->ld_options.ldo_mutex ); rc = ber_write( &tmpber, ld->ld_options.ldo_peer, sizeof( struct sockaddr_storage ), 0 ); LDAP_MUTEX_UNLOCK( &ld->ld_options.ldo_mutex ); if ( rc == -1 ) { ld->ld_errno = LDAP_ENCODING_ERROR; LDAP_CONN_UNLOCK_IF(m_noconn); return rc; } } #endif /* If we still have an incomplete write, try to finish it before * dealing with the new request. If we don't finish here, return * LDAP_BUSY and let the caller retry later. We only allow a single * request to be in WRITING state. */ rc = 0; if ( ld->ld_requests && ld->ld_requests->lr_status == LDAP_REQST_WRITING && ldap_int_flush_request( ld, ld->ld_requests ) < 0 ) { rc = -1; } if ( rc ) { LDAP_CONN_UNLOCK_IF(m_noconn); return rc; } lr = (LDAPRequest *)LDAP_CALLOC( 1, sizeof( LDAPRequest ) ); if ( lr == NULL ) { ld->ld_errno = LDAP_NO_MEMORY; ldap_free_connection( ld, lc, 0, 0 ); ber_free( ber, 1 ); if ( incparent ) { /* Forget about the bind */ --parentreq->lr_outrefcnt; } LDAP_CONN_UNLOCK_IF(m_noconn); return( -1 ); } lr->lr_msgid = msgid; lr->lr_status = LDAP_REQST_INPROGRESS; lr->lr_res_errno = LDAP_SUCCESS; /* optimistic */ lr->lr_ber = ber; lr->lr_conn = lc; if ( parentreq != NULL ) { /* sub-request */ if ( !incparent ) { /* Increment if we didn't do it before the bind */ ++parentreq->lr_outrefcnt; } lr->lr_origid = parentreq->lr_origid; lr->lr_parentcnt = ++parentreq->lr_parentcnt; lr->lr_parent = parentreq; lr->lr_refnext = parentreq->lr_child; parentreq->lr_child = lr; } else { /* original request */ lr->lr_origid = lr->lr_msgid; } /* Extract requestDN for future reference */ #ifdef LDAP_CONNECTIONLESS if ( !LDAP_IS_UDP(ld) ) #endif { BerElement tmpber = *ber; ber_int_t bint; ber_tag_t tag, rtag; ber_reset( &tmpber, 1 ); rtag = ber_scanf( &tmpber, "{it", /*}*/ &bint, &tag ); switch ( tag ) { case LDAP_REQ_BIND: rtag = ber_scanf( &tmpber, "{i" /*}*/, &bint ); break; case LDAP_REQ_DELETE: break; default: rtag = ber_scanf( &tmpber, "{" /*}*/ ); case LDAP_REQ_ABANDON: break; } if ( tag != LDAP_REQ_ABANDON ) { ber_skip_tag( &tmpber, &lr->lr_dn.bv_len ); lr->lr_dn.bv_val = tmpber.ber_ptr; } } lr->lr_prev = NULL; lr->lr_next = ld->ld_requests; if ( lr->lr_next != NULL ) { lr->lr_next->lr_prev = lr; } ld->ld_requests = lr; ld->ld_errno = LDAP_SUCCESS; if ( ldap_int_flush_request( ld, lr ) == -1 ) { msgid = -1; } LDAP_CONN_UNLOCK_IF(m_noconn); return( msgid ); }
/* 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 ); }
static int ber_put_int_or_enum( BerElement *ber, ber_int_t num, ber_tag_t tag ) { int rc; int i, j, sign, taglen, lenlen; ber_len_t len; ber_uint_t unum, mask; unsigned char netnum[sizeof(ber_uint_t)]; assert( ber != NULL ); assert( LBER_VALID( ber ) ); sign = (num < 0); unum = num; /* Bit fiddling should be done with unsigned values */ /* * high bit is set - look for first non-all-one byte * high bit is clear - look for first non-all-zero byte */ i = BER_TOP_BYTE(ber_int_t); mask = BER_TOP_MASK(ber_uint_t); for ( ; i > 0; i-- ) { if ( sign ) { /* not all ones */ if ( (unum & mask) != mask ) break; } else { /* not all zero */ if ( unum & mask ) break; } mask >>= 8; } /* * we now have the "leading byte". if the high bit on this * byte matches the sign bit, we need to "back up" a byte. */ mask = (unum & ((ber_uint_t)0x80U << (i * 8))); if ( (mask && !sign) || (sign && !mask) ) { i++; } len = i + 1; if ( (taglen = ber_put_tag( ber, tag, 0 )) == -1 ) { return -1; } if ( (lenlen = ber_put_len( ber, len, 0 )) == -1 ) { return -1; } i++; for( j=i-1; j>=0; j-- ) { netnum[j] = (unsigned char)(unum & 0xffU); unum >>= 8; } rc = ber_write( ber, (char *) netnum, i, 0 ); /* length of tag + length + contents */ return rc == i ? taglen + lenlen + i : -1; }
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 ); }
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 ); }
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 ); }
static long ber_ctrl(BIO *b, int cmd, long num, char *ptr) { BIO *dbio; BIO_ENC_CTX *ctx,*dctx; long ret=1; int i; ctx=(BIO_ENC_CTX *)b->ptr; switch (cmd) { case BIO_CTRL_RESET: ctx->ok=1; ctx->finished=0; EVP_CipherInit_ex(&(ctx->cipher),NULL,NULL,NULL,NULL, ctx->cipher.berrypt); ret=BIO_ctrl(b->next_bio,cmd,num,ptr); break; case BIO_CTRL_EOF: /* More to read */ if (ctx->cont <= 0) ret=1; else ret=BIO_ctrl(b->next_bio,cmd,num,ptr); break; case BIO_CTRL_WPENDING: ret=ctx->buf_len-ctx->buf_off; if (ret <= 0) ret=BIO_ctrl(b->next_bio,cmd,num,ptr); break; case BIO_CTRL_PENDING: /* More to read in buffer */ ret=ctx->buf_len-ctx->buf_off; if (ret <= 0) ret=BIO_ctrl(b->next_bio,cmd,num,ptr); break; case BIO_CTRL_FLUSH: /* do a final write */ again: while (ctx->buf_len != ctx->buf_off) { i=ber_write(b,NULL,0); if (i < 0) { ret=i; break; } } if (!ctx->finished) { ctx->finished=1; ctx->buf_off=0; ret=EVP_CipherFinal_ex(&(ctx->cipher), (unsigned char *)ctx->buf, &(ctx->buf_len)); ctx->ok=(int)ret; if (ret <= 0) break; /* push out the bytes */ goto again; } /* Finally flush the underlying BIO */ ret=BIO_ctrl(b->next_bio,cmd,num,ptr); break; case BIO_C_GET_CIPHER_STATUS: ret=(long)ctx->ok; break; case BIO_C_DO_STATE_MACHINE: BIO_clear_retry_flags(b); ret=BIO_ctrl(b->next_bio,cmd,num,ptr); BIO_copy_next_retry(b); break; case BIO_CTRL_DUP: dbio=(BIO *)ptr; dctx=(BIO_ENC_CTX *)dbio->ptr; memcpy(&(dctx->cipher),&(ctx->cipher),sizeof(ctx->cipher)); dbio->init=1; break; default: ret=BIO_ctrl(b->next_bio,cmd,num,ptr); break; } return(ret); }
static int do_abandon( LDAP *ld, ber_int_t origid, ber_int_t msgid, LDAPControl **sctrls, LDAPControl **cctrls) { BerElement *ber; int i, err, sendabandon; ber_int_t *old_abandon; Sockbuf *sb; LDAPRequest *lr; #ifdef NEW_LOGGING LDAP_LOG ( OPERATION, ARGS, "do_abandon %d, msgid %d\n", origid, msgid, 0 ); #else Debug( LDAP_DEBUG_TRACE, "do_abandon origid %d, msgid %d\n", origid, msgid, 0 ); #endif sendabandon = 1; /* find the request that we are abandoning */ for ( lr = ld->ld_requests; lr != NULL; lr = lr->lr_next ) { if ( lr->lr_msgid == msgid ) { /* this message */ break; } if ( lr->lr_origid == msgid ) {/* child: abandon it */ (void) do_abandon( ld, msgid, lr->lr_msgid, sctrls, cctrls ); } } 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; } } if ( ldap_msgdelete( ld, msgid ) == 0 ) { ld->ld_errno = LDAP_SUCCESS; return LDAP_SUCCESS; } 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 alocation failed */ err = -1; ld->ld_errno = LDAP_NO_MEMORY; } else { #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, "{isti", /* '}' */ ++ld->ld_msgid, dn, LDAP_REQ_ABANDON, msgid ); } else #endif { /* create a message to send */ err = ber_printf( ber, "{iti", /* '}' */ ++ld->ld_msgid, 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 ) { sb = lr->lr_conn->lconn_sb; } else { sb = ld->ld_sb; } if ( ber_flush( sb, ber, 1 ) != 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 ); } } i = 0; if ( ld->ld_abandoned != NULL ) { for ( ; ld->ld_abandoned[i] != -1; i++ ) ; /* NULL */ } old_abandon = ld->ld_abandoned; ld->ld_abandoned = (ber_int_t *) LDAP_REALLOC( (char *) ld->ld_abandoned, (i + 2) * sizeof(ber_int_t) ); if ( ld->ld_abandoned == NULL ) { ld->ld_abandoned = old_abandon; ld->ld_errno = LDAP_NO_MEMORY; return( ld->ld_errno ); } ld->ld_abandoned[i] = msgid; ld->ld_abandoned[i + 1] = -1; if ( err != -1 ) { ld->ld_errno = LDAP_SUCCESS; } return( ld->ld_errno ); }