📄 request.c
字号:
/*
* Copyright (c) 1995 Regents of the University of Michigan.
* All rights reserved.
*
* request.c - sending of ldap requests; handling of referrals
*/
#ifndef lint
static char copyright[] = "@(#) Copyright (c) 1995 Regents of the University "
"of Michigan.\nAll rights reserved.\n";
#endif
#include <stdio.h>
#include <string.h>
#if PGPSOCKETSLDAP /* jason */
#include "pgpSocketsLDAP.h"
#else
#ifdef MACOS
#include <stdlib.h>
#include <time.h>
#include "macos.h"
#else /* MACOS */
#if defined( DOS ) || defined( _WIN32 )
#ifdef DOS
#include "msdos.h"
#endif
#include <time.h>
#include <stdlib.h>
#ifdef PCNFS
#include <tklib.h>
#include <tk_errno.h>
#include <bios.h>
#endif /* PCNFS */
#ifdef NCSA
#include "externs.h"
#endif /* NCSA */
#else /* DOS */
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#ifdef _AIX
#include <sys/select.h>
#endif /* _AIX */
#include "portable.h"
#endif /* DOS */
#endif /* MACOS */
#ifdef VMS
#include "ucx_select.h"
#endif
#endif /* PGPSOCKETSLDAP */
#include "lber.h"
#include "ldap.h"
#include "ldap-int.h"
#ifdef USE_SYSCONF
#include <unistd.h>
#endif /* USE_SYSCONF */
#if defined( LDAP_REFERRALS ) || defined( LDAP_DNS )
#ifdef NEEDPROTOS
static LDAPConn *find_connection( LDAP *ld, LDAPServer *srv, int any );
static void use_connection( LDAP *ld, LDAPConn *lc );
static void free_servers( LDAPServer *srvlist );
#else /* NEEDPROTOS */
static LDAPConn *find_connection();
static void use_connection();
static void free_servers();
#endif /* NEEDPROTOS */
#endif /* LDAP_REFERRALS || LDAP_DNS */
#ifdef LDAP_DNS
#ifdef NEEDPROTOS
static LDAPServer *dn2servers( LDAP *ld, char *dn );
#else /* NEEDPROTOS */
static LDAPServer *dn2servers();
#endif /* NEEDPROTOS */
#endif /* LDAP_DNS */
#ifdef LDAP_REFERRALS
#ifdef NEEDPROTOS
static BerElement *re_encode_request( LDAP *ld, BerElement *origber,
int msgid, char **dnp );
#else /* NEEDPROTOS */
static BerElement *re_encode_request();
#endif /* NEEDPROTOS */
#endif /* LDAP_REFERRALS */
BerElement *
alloc_ber_with_options( LDAP *ld )
{
BerElement *ber;
if (( ber = ber_alloc_t( ld->ld_lberoptions )) == NULLBER ) {
ld->ld_errno = LDAP_NO_MEMORY;
#ifdef STR_TRANSLATION
} else {
set_ber_options( ld, ber );
#endif /* STR_TRANSLATION */
}
return( ber );
}
void
set_ber_options( LDAP *ld, BerElement *ber )
{
ber->ber_options = ld->ld_lberoptions;
#ifdef STR_TRANSLATION
if (( ld->ld_lberoptions & LBER_TRANSLATE_STRINGS ) != 0 ) {
ber_set_string_translators( ber,
ld->ld_lber_encode_translate_proc,
ld->ld_lber_decode_translate_proc );
}
#endif /* STR_TRANSLATION */
}
int
send_initial_request( LDAP *ld, unsigned long msgtype, char *dn,
BerElement *ber )
{
#if defined( LDAP_REFERRALS ) || defined( LDAP_DNS )
LDAPServer *servers;
#endif /* LDAP_REFERRALS || LDAP_DNS */
(void) msgtype;
(void) dn;
Debug( LDAP_DEBUG_TRACE, "send_initial_request\n", 0, 0, 0 );
#if !defined( LDAP_REFERRALS ) && !defined( LDAP_DNS )
if ( ber_flush( &ld->ld_sb, ber, 1 ) != 0 ) {
ld->ld_errno = LDAP_SERVER_DOWN;
return( -1 );
}
ld->ld_errno = LDAP_SUCCESS;
return( ld->ld_msgid );
#else /* !LDAP_REFERRALS && !LDAP_DNS */
#ifdef LDAP_DNS
if (( ld->ld_options & LDAP_OPT_DNS ) != 0 && ldap_is_dns_dn( dn )) {
if (( servers = dn2servers( ld, dn )) == NULL ) {
ber_free( ber, 1 );
return( -1 );
}
#ifdef LDAP_DEBUG
if ( ldap_debug & LDAP_DEBUG_TRACE ) {
LDAPServer *srv;
for ( srv = servers; srv != NULL;
srv = srv->lsrv_next ) {
fprintf( stderr,
"LDAP server %s: dn %s, port %d\n",
srv->lsrv_host, ( srv->lsrv_dn == NULL ) ?
"(default)" : srv->lsrv_dn,
srv->lsrv_port );
}
}
#endif /* LDAP_DEBUG */
} else {
#endif /* LDAP_DNS */
/*
* use of DNS is turned off or this is an X.500 DN...
* use our default connection
*/
servers = NULL;
#ifdef LDAP_DNS
}
#endif /* LDAP_DNS */
return( send_server_request( ld, ber, ld->ld_msgid, NULL, servers,
NULL, 0 ));
#endif /* !LDAP_REFERRALS && !LDAP_DNS */
}
#if defined( LDAP_REFERRALS ) || defined( LDAP_DNS )
int
send_server_request( LDAP *ld, BerElement *ber, int msgid, LDAPRequest
*parentreq, LDAPServer *srvlist, LDAPConn *lc, int bind )
{
LDAPRequest *lr;
Debug( LDAP_DEBUG_TRACE, "send_server_request\n", 0, 0, 0 );
ld->ld_errno = LDAP_SUCCESS; /* optimistic */
if ( lc == NULL ) {
if ( srvlist == NULL ) {
lc = ld->ld_defconn;
} else {
if (( lc = find_connection( ld, srvlist, 1 )) ==
NULL ) {
lc = new_connection( ld, &srvlist, 0, 1, bind );
}
free_servers( srvlist );
}
}
if ( lc == NULL || lc->lconn_status != LDAP_CONNST_CONNECTED ) {
ber_free( ber, 1 );
if ( ld->ld_errno == LDAP_SUCCESS ) {
ld->ld_errno = LDAP_SERVER_DOWN;
}
return( -1 );
}
use_connection( ld, lc );
if (( lr = (LDAPRequest *)calloc( 1, sizeof( LDAPRequest ))) ==
NULL ) {
ld->ld_errno = LDAP_NO_MEMORY;
free_connection( ld, lc, 0, 0 );
ber_free( ber, 1 );
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 */
++parentreq->lr_outrefcnt;
lr->lr_origid = parentreq->lr_origid;
lr->lr_parentcnt = parentreq->lr_parentcnt + 1;
lr->lr_parent = parentreq;
lr->lr_refnext = parentreq->lr_refnext;
parentreq->lr_refnext = lr;
} else { /* original request */
lr->lr_origid = lr->lr_msgid;
}
if (( lr->lr_next = ld->ld_requests ) != NULL ) {
lr->lr_next->lr_prev = lr;
}
ld->ld_requests = lr;
lr->lr_prev = NULL;
if ( ber_flush( lc->lconn_sb, ber, 0 ) != 0 ) {
#ifdef notyet
extern int errno;
if ( errno == EWOULDBLOCK ) {
/* need to continue write later */
lr->lr_status = LDAP_REQST_WRITING;
mark_select_write( ld, lc->lconn_sb );
} else {
#else /* notyet */
ld->ld_errno = LDAP_SERVER_DOWN;
free_request( ld, lr );
free_connection( ld, lc, 0, 0 );
return( -1 );
#endif /* notyet */
#ifdef notyet
}
#endif /* notyet */
} else {
if ( parentreq == NULL ) {
ber->ber_end = ber->ber_ptr;
ber->ber_ptr = ber->ber_buf;
}
/* sent -- waiting for a response */
mark_select_read( ld, lc->lconn_sb );
}
ld->ld_errno = LDAP_SUCCESS;
return( msgid );
}
LDAPConn *
new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb,
int connect, int bind )
{
LDAPConn *lc;
LDAPServer *prevsrv, *srv;
Sockbuf *sb;
/*
* make a new LDAP server connection
* XXX open connection synchronously for now
*/
if (( lc = (LDAPConn *)calloc( 1, sizeof( LDAPConn ))) == NULL ||
( !use_ldsb && ( sb = (Sockbuf *)calloc( 1, sizeof( Sockbuf )))
== NULL )) {
if ( lc != NULL ) {
free( (char *)lc );
}
ld->ld_errno = LDAP_NO_MEMORY;
return( NULL );
}
lc->lconn_sb = ( use_ldsb ) ? &ld->ld_sb : sb;
if ( connect ) {
prevsrv = NULL;
for ( srv = *srvlistp; srv != NULL; srv = srv->lsrv_next ) {
if ( open_ldap_connection( ld, lc->lconn_sb,
srv->lsrv_host, srv->lsrv_port,
&lc->lconn_krbinstance, 0 ) != -1 ) {
break;
}
prevsrv = srv;
}
if ( srv == NULL ) {
if ( !use_ldsb ) {
free( (char *)lc->lconn_sb );
}
free( (char *)lc );
ld->ld_errno = LDAP_SERVER_DOWN;
return( NULL );
}
if ( prevsrv == NULL ) {
*srvlistp = srv->lsrv_next;
} else {
prevsrv->lsrv_next = srv->lsrv_next;
}
lc->lconn_server = srv;
}
lc->lconn_status = LDAP_CONNST_CONNECTED;
lc->lconn_next = ld->ld_conns;
ld->ld_conns = lc;
/*
* XXX for now, we always do a synchronous bind. This will have
* to change in the long run...
*/
if ( bind ) {
int err, freepasswd, authmethod;
char *binddn, *passwd;
LDAPConn *savedefconn;
freepasswd = err = 0;
if ( ld->ld_rebindproc == NULL ) {
binddn = passwd = "";
authmethod = LDAP_AUTH_SIMPLE;
} else {
if (( err = (*ld->ld_rebindproc)( ld, &binddn, &passwd,
&authmethod, 0 )) == LDAP_SUCCESS ) {
freepasswd = 1;
} else {
ld->ld_errno = err;
err = -1;
}
}
if ( err == 0 ) {
savedefconn = ld->ld_defconn;
ld->ld_defconn = lc;
++lc->lconn_refcnt; /* avoid premature free */
if ( ldap_bind_s( ld, binddn, passwd, authmethod ) !=
LDAP_SUCCESS ) {
err = -1;
}
--lc->lconn_refcnt;
ld->ld_defconn = savedefconn;
}
if ( freepasswd ) {
(*ld->ld_rebindproc)( ld, &binddn, &passwd,
&authmethod, 1 );
}
if ( err != 0 ) {
free_connection( ld, lc, 1, 0 );
lc = NULL;
}
}
return( lc );
}
static LDAPConn *
find_connection( LDAP *ld, LDAPServer *srv, int any )
/*
* return an existing connection (if any) to the server srv
* if "any" is non-zero, check for any server in the "srv" chain
*/
{
LDAPConn *lc;
LDAPServer *ls;
for ( lc = ld->ld_conns; lc != NULL; lc = lc->lconn_next ) {
for ( ls = srv; ls != NULL; ls = ls->lsrv_next ) {
if ( lc->lconn_server->lsrv_host != NULL &&
ls->lsrv_host != NULL && strcasecmp(
ls->lsrv_host, lc->lconn_server->lsrv_host ) == 0
&& ls->lsrv_port == lc->lconn_server->lsrv_port ) {
return( lc );
}
if ( !any ) {
break;
}
}
}
return( NULL );
}
static void
use_connection( LDAP *ld, LDAPConn *lc )
{
(void) ld;
++lc->lconn_refcnt;
lc->lconn_lastused = time( 0 );
}
void
free_connection( LDAP *ld, LDAPConn *lc, int force, int unbind )
{
LDAPConn *tmplc, *prevlc;
Debug( LDAP_DEBUG_TRACE, "free_connection\n", 0, 0, 0 );
if ( force || --lc->lconn_refcnt <= 0 ) {
if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) {
mark_select_clear( ld, lc->lconn_sb );
if ( unbind ) {
send_unbind( ld, lc->lconn_sb );
}
close_connection( lc->lconn_sb );
if ( lc->lconn_sb->sb_ber.ber_buf != NULL ) {
free( lc->lconn_sb->sb_ber.ber_buf );
}
}
prevlc = NULL;
for ( tmplc = ld->ld_conns; tmplc != NULL;
tmplc = tmplc->lconn_next ) {
if ( tmplc == lc ) {
if ( prevlc == NULL ) {
ld->ld_conns = tmplc->lconn_next;
} else {
prevlc->lconn_next = tmplc->lconn_next;
}
break;
}
}
free_servers( lc->lconn_server );
if ( lc->lconn_krbinstance != NULL ) {
free( lc->lconn_krbinstance );
}
if ( lc->lconn_sb != &ld->ld_sb ) {
free( (char *)lc->lconn_sb );
}
free( lc );
Debug( LDAP_DEBUG_TRACE, "free_connection: actually freed\n",
0, 0, 0 );
} else {
lc->lconn_lastused = time( 0 );
Debug( LDAP_DEBUG_TRACE, "free_connection: refcnt %d\n",
lc->lconn_refcnt, 0, 0 );
}
}
#ifdef LDAP_DEBUG
void
dump_connection( LDAP *ld, LDAPConn *lconns, int all )
{
LDAPConn *lc;
fprintf( stderr, "** Connection%s:\n", all ? "s" : "" );
for ( lc = lconns; lc != NULL; lc = lc->lconn_next ) {
if ( lc->lconn_server != NULL ) {
fprintf( stderr, "* host: %s port: %d%s\n",
( lc->lconn_server->lsrv_host == NULL ) ? "(null)"
: lc->lconn_server->lsrv_host,
lc->lconn_server->lsrv_port, ( lc->lconn_sb ==
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -