/* returns 0 if connection opened and -1 if an error occurs */ int nsldapi_open_ldap_defconn( LDAP *ld ) { LDAPServer *srv; if (( srv = (LDAPServer *)NSLDAPI_CALLOC( 1, sizeof( LDAPServer ))) == NULL || ( ld->ld_defhost != NULL && ( srv->lsrv_host = nsldapi_strdup( ld->ld_defhost )) == NULL )) { LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); return( -1 ); } srv->lsrv_port = ld->ld_defport; #ifdef LDAP_SSLIO_HOOKS if (( ld->ld_options & LDAP_BITOPT_SSL ) != 0 ) { srv->lsrv_options |= LDAP_SRV_OPT_SECURE; } #endif if (( ld->ld_defconn = nsldapi_new_connection( ld, &srv, 1, 1, 0 )) == NULL ) { if ( ld->ld_defhost != NULL ) { NSLDAPI_FREE( srv->lsrv_host ); } NSLDAPI_FREE( (char *)srv ); return( -1 ); } ++ld->ld_defconn->lconn_refcnt; /* so it never gets closed/freed */ return( 0 ); }
void LDAP_CALL ldap_value_free(char **vals) { int i; if (vals == NULL) return; for (i = 0; vals[i] != NULL; i++) NSLDAPI_FREE(vals[i]); NSLDAPI_FREE((char *)vals); }
void LDAP_CALL ldap_free_sort_keylist ( LDAPsortkey **sortKeyList ) { LDAPsortkey *this_one = NULL; int i = 0; if ( NULL == sortKeyList ) { return; } /* Walk down the list freeing the LDAPsortkey structures */ for (this_one = sortKeyList[0]; this_one ; this_one = sortKeyList[++i]) { /* Free the strings, if present */ if (NULL != this_one->sk_attrtype) { NSLDAPI_FREE(this_one->sk_attrtype); } if (NULL != this_one->sk_matchruleoid) { NSLDAPI_FREE(this_one->sk_matchruleoid); } NSLDAPI_FREE(this_one); } /* Free the pointer list */ NSLDAPI_FREE(sortKeyList); }
void nsldapi_free_connection( LDAP *ld, LDAPConn *lc, LDAPControl **serverctrls, LDAPControl **clientctrls, int force, int unbind ) { LDAPConn *tmplc, *prevlc; LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_free_connection\n", 0, 0, 0 ); if ( force || --lc->lconn_refcnt <= 0 ) { if ( lc->lconn_status == LDAP_CONNST_CONNECTED ) { nsldapi_iostatus_interest_clear( ld, lc->lconn_sb ); if ( unbind ) { nsldapi_send_unbind( ld, lc->lconn_sb, serverctrls, clientctrls ); } } nsldapi_close_connection( ld, lc->lconn_sb ); 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; } prevlc = tmplc; } free_servers( lc->lconn_server ); if ( lc->lconn_krbinstance != NULL ) { NSLDAPI_FREE( lc->lconn_krbinstance ); } /* * if this is the default connection (lc->lconn_sb==ld->ld_sbp) * we do not free the Sockbuf here since it will be freed * later inside ldap_unbind(). */ if ( lc->lconn_sb != ld->ld_sbp ) { ber_sockbuf_free( lc->lconn_sb ); lc->lconn_sb = NULL; } if ( lc->lconn_ber != NULLBER ) { ber_free( lc->lconn_ber, 1 ); } if ( lc->lconn_binddn != NULL ) { NSLDAPI_FREE( lc->lconn_binddn ); } NSLDAPI_FREE( lc ); LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_free_connection: actually freed\n", 0, 0, 0 ); } else { lc->lconn_lastused = time( 0 ); LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_free_connection: refcnt %d\n", lc->lconn_refcnt, 0, 0 ); } }
void LDAP_CALL ldap_x_hostlist_statusfree(struct ldap_x_hostlist_status *status) { if (NULL != status) { if (NULL != status->lhs_hostlist) { NSLDAPI_FREE(status->lhs_hostlist); } NSLDAPI_FREE(status); } }
void LDAP_CALL ldap_value_free_len(struct berval **vals) { int i; if (vals == NULL) return; for (i = 0; vals[i] != NULL; i++) { NSLDAPI_FREE(vals[i]->bv_val); NSLDAPI_FREE(vals[i]); } NSLDAPI_FREE((char *)vals); }
void nsldapi_free_request( LDAP *ld, LDAPRequest *lr, int free_conn ) { LDAPRequest *tmplr, *nextlr; LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_free_request 0x%x (origid %d, msgid %d)\n", lr, lr->lr_origid, lr->lr_msgid ); if ( lr->lr_parent != NULL ) { --lr->lr_parent->lr_outrefcnt; } /* free all of our spawned referrals (child requests) */ for ( tmplr = lr->lr_child; tmplr != NULL; tmplr = nextlr ) { nextlr = tmplr->lr_sibling; nsldapi_free_request( ld, tmplr, free_conn ); } if ( free_conn ) { nsldapi_free_connection( ld, lr->lr_conn, NULL, NULL, 0, 1 ); } if ( lr->lr_prev == NULL ) { ld->ld_requests = lr->lr_next; } else { lr->lr_prev->lr_next = lr->lr_next; } if ( lr->lr_next != NULL ) { lr->lr_next->lr_prev = lr->lr_prev; } if ( lr->lr_ber != NULL ) { ber_free( lr->lr_ber, 1 ); } if ( lr->lr_res_error != NULL ) { NSLDAPI_FREE( lr->lr_res_error ); } if ( lr->lr_res_matched != NULL ) { NSLDAPI_FREE( lr->lr_res_matched ); } if ( lr->lr_binddn != NULL ) { NSLDAPI_FREE( lr->lr_binddn ); } NSLDAPI_FREE( lr ); }
void LDAP_CALL ldap_control_free( LDAPControl *ctrl ) { if ( ctrl != NULL ) { if ( ctrl->ldctl_oid != NULL ) { NSLDAPI_FREE( ctrl->ldctl_oid ); } if ( ctrl->ldctl_value.bv_val != NULL ) { NSLDAPI_FREE( ctrl->ldctl_value.bv_val ); } NSLDAPI_FREE( (char *)ctrl ); } }
void LDAP_CALL ldap_free_urldesc( LDAPURLDesc *ludp ) { if ( ludp != NULLLDAPURLDESC ) { if ( ludp->lud_string != NULL ) { NSLDAPI_FREE( ludp->lud_string ); } if ( ludp->lud_attrs != NULL ) { NSLDAPI_FREE( ludp->lud_attrs ); } NSLDAPI_FREE( ludp ); } }
/* * build an allocated LDAPv3 control. Returns an LDAP error code. */ int nsldapi_build_control( char *oid, BerElement *ber, int freeber, char iscritical, LDAPControl **ctrlp ) { int rc; struct berval *bvp; if ( ber == NULL ) { bvp = NULL; } else { /* allocate struct berval with contents of the BER encoding */ rc = ber_flatten( ber, &bvp ); if ( freeber ) { ber_free( ber, 1 ); } if ( rc == -1 ) { return( LDAP_NO_MEMORY ); } } /* allocate the new control structure */ if (( *ctrlp = (LDAPControl *)NSLDAPI_MALLOC( sizeof(LDAPControl))) == NULL ) { if ( bvp != NULL ) { ber_bvfree( bvp ); } return( LDAP_NO_MEMORY ); } /* fill in the fields of this new control */ (*ctrlp)->ldctl_iscritical = iscritical; if (( (*ctrlp)->ldctl_oid = nsldapi_strdup( oid )) == NULL ) { NSLDAPI_FREE( *ctrlp ); if ( bvp != NULL ) { ber_bvfree( bvp ); } return( LDAP_NO_MEMORY ); } if ( bvp == NULL ) { (*ctrlp)->ldctl_value.bv_len = 0; (*ctrlp)->ldctl_value.bv_val = NULL; } else { (*ctrlp)->ldctl_value = *bvp; /* struct copy */ NSLDAPI_FREE( bvp ); /* free container, not contents! */ } return( LDAP_SUCCESS ); }
/* * duplicate the contents of "ctrl_src" and place in "ctrl_dst" */ static int /* LDAP_CALL */ /* keep this routine internal for now */ ldap_control_copy_contents( LDAPControl *ctrl_dst, LDAPControl *ctrl_src ) { size_t len; if ( NULL == ctrl_dst || NULL == ctrl_src ) { return( LDAP_PARAM_ERROR ); } ctrl_dst->ldctl_iscritical = ctrl_src->ldctl_iscritical; /* fill in the fields of this new control */ if (( ctrl_dst->ldctl_oid = nsldapi_strdup( ctrl_src->ldctl_oid )) == NULL ) { return( LDAP_NO_MEMORY ); } len = (size_t)(ctrl_src->ldctl_value).bv_len; if ( ctrl_src->ldctl_value.bv_val == NULL || len <= 0 ) { ctrl_dst->ldctl_value.bv_len = 0; ctrl_dst->ldctl_value.bv_val = NULL; } else { ctrl_dst->ldctl_value.bv_len = len; if (( ctrl_dst->ldctl_value.bv_val = NSLDAPI_MALLOC( len )) == NULL ) { NSLDAPI_FREE( ctrl_dst->ldctl_oid ); return( LDAP_NO_MEMORY ); } SAFEMEMCPY( ctrl_dst->ldctl_value.bv_val, ctrl_src->ldctl_value.bv_val, len ); } return ( LDAP_SUCCESS ); }
void nsldapi_handle_reconnect( LDAP *ld ) { LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_handle_reconnect\n", 0, 0, 0 ); /* * if the default connection has been lost and is now marked dead, * dispose of the default connection so it will get re-established. * * if not, clear the bind DN and status to ensure that we don't * report the wrong bind DN to a different thread while waiting * for our bind result to return from the server. */ LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); if ( NULL != ld->ld_defconn ) { if ( LDAP_CONNST_DEAD == ld->ld_defconn->lconn_status ) { nsldapi_free_connection( ld, ld->ld_defconn, NULL, NULL, 1, 0 ); ld->ld_defconn = NULL; } else if ( ld->ld_defconn->lconn_binddn != NULL ) { NSLDAPI_FREE( ld->ld_defconn->lconn_binddn ); ld->ld_defconn->lconn_binddn = NULL; ld->ld_defconn->lconn_bound = 0; } } LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); }
LDAP_CALL ldap_getfirstfilter( LDAPFiltDesc *lfdp, char *tagpat, char *value ) { LDAPFiltList *flp; if ( lfdp == NULL || tagpat == NULL || value == NULL ) { return( NULL ); /* punt */ } if ( lfdp->lfd_curvalcopy != NULL ) { NSLDAPI_FREE( lfdp->lfd_curvalcopy ); NSLDAPI_FREE( lfdp->lfd_curvalwords ); } NSLDAPI_FREE(lfdp->lfd_curval); if ((lfdp->lfd_curval = nsldapi_strdup(value)) == NULL) { return( NULL ); } lfdp->lfd_curfip = NULL; for ( flp = lfdp->lfd_filtlist; flp != NULL; flp = flp->lfl_next ) { if ( re_comp( tagpat ) == NULL && re_exec( flp->lfl_tag ) == 1 && re_comp( flp->lfl_pattern ) == NULL && re_exec( lfdp->lfd_curval ) == 1 ) { lfdp->lfd_curfip = flp->lfl_ilist; break; } } if ( lfdp->lfd_curfip == NULL ) { return( NULL ); } if (( lfdp->lfd_curvalcopy = nsldapi_strdup( value )) == NULL ) { return( NULL ); } if ( break_into_words( lfdp->lfd_curvalcopy, flp->lfl_delims, &lfdp->lfd_curvalwords ) < 0 ) { NSLDAPI_FREE( lfdp->lfd_curvalcopy ); lfdp->lfd_curvalcopy = NULL; return( NULL ); } return( ldap_getnextfilter( lfdp )); }
int LDAP_CALL ldap_init_templates( char *file, struct ldap_disptmpl **tmpllistp ) { FILE *fp; char *buf; long rlen, len; int rc, eof; *tmpllistp = NULLDISPTMPL; if (( fp = fopen( file, "rF" )) == NULL ) { return( LDAP_TMPL_ERR_FILE ); } if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */ fclose( fp ); return( LDAP_TMPL_ERR_FILE ); } len = ftell( fp ); if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */ fclose( fp ); return( LDAP_TMPL_ERR_FILE ); } if (( buf = NSLDAPI_MALLOC( (size_t)len )) == NULL ) { fclose( fp ); return( LDAP_TMPL_ERR_MEM ); } rlen = fread( buf, 1, (size_t)len, fp ); eof = feof( fp ); fclose( fp ); if ( rlen != len && !eof ) { /* error: didn't get the whole file */ NSLDAPI_FREE( buf ); return( LDAP_TMPL_ERR_FILE ); } rc = ldap_init_templates_buf( buf, rlen, tmpllistp ); NSLDAPI_FREE( buf ); return( rc ); }
static void free_servers( LDAPServer *srvlist ) { LDAPServer *nextsrv; while ( srvlist != NULL ) { nextsrv = srvlist->lsrv_next; if ( srvlist->lsrv_dn != NULL ) { NSLDAPI_FREE( srvlist->lsrv_dn ); } if ( srvlist->lsrv_host != NULL ) { NSLDAPI_FREE( srvlist->lsrv_host ); } NSLDAPI_FREE( srvlist ); srvlist = nextsrv; } }
LDAP_CALL ldap_init_getfilter( char *fname ) { FILE *fp; char *buf; long rlen, len; int eof; LDAPFiltDesc *lfdp; if (( fp = NSLDAPI_FOPEN( fname, "r" )) == NULL ) { return( NULL ); } if ( fseek( fp, 0L, SEEK_END ) != 0 ) { /* move to end to get len */ fclose( fp ); return( NULL ); } len = ftell( fp ); if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { /* back to start of file */ fclose( fp ); return( NULL ); } if (( buf = NSLDAPI_MALLOC( (size_t)len )) == NULL ) { fclose( fp ); return( NULL ); } rlen = fread( buf, 1, (size_t)len, fp ); eof = feof( fp ); fclose( fp ); if ( rlen != len && !eof ) { /* error: didn't get the whole file */ NSLDAPI_FREE( buf ); return( NULL ); } lfdp = ldap_init_getfilter_buf( buf, rlen ); NSLDAPI_FREE( buf ); return( lfdp ); }
int LDAP_CALL ldap_set_filter_additions(LDAPFiltDesc *lfdp, char *prefix, char *suffix) { if (lfdp == NULL) { return (LDAP_PARAM_ERROR); } if (lfdp->lfd_filtprefix != NULL) { NSLDAPI_FREE(lfdp->lfd_filtprefix); } lfdp->lfd_filtprefix = (prefix == NULL) ? NULL : nsldapi_strdup(prefix); if (lfdp->lfd_filtsuffix != NULL) { NSLDAPI_FREE(lfdp->lfd_filtsuffix); } lfdp->lfd_filtsuffix = (suffix == NULL) ? NULL : nsldapi_strdup(suffix); return (LDAP_SUCCESS); }
void LDAP_CALL ldap_controls_free( LDAPControl **ctrls ) { int i; if ( ctrls != NULL ) { for ( i = 0; ctrls[i] != NULL; i++ ) { ldap_control_free( ctrls[i] ); } NSLDAPI_FREE( (char *)ctrls ); } }
LDAP_CALL ldap_explode_dns( const char *dn ) { int ncomps, maxcomps; char *s, *cpydn; char **rdns; #ifdef HAVE_STRTOK_R /* defined in portable.h */ char *lasts; #endif if ( dn == NULL ) { dn = ""; } if ( (rdns = (char **)NSLDAPI_MALLOC( 8 * sizeof(char *) )) == NULL ) { return( NULL ); } maxcomps = 8; ncomps = 0; cpydn = nsldapi_strdup( (char *)dn ); for ( s = STRTOK( cpydn, "@.", &lasts ); s != NULL; s = STRTOK( NULL, "@.", &lasts ) ) { if ( ncomps == maxcomps ) { maxcomps *= 2; if ( (rdns = (char **)NSLDAPI_REALLOC( rdns, maxcomps * sizeof(char *) )) == NULL ) { NSLDAPI_FREE( cpydn ); return( NULL ); } } rdns[ncomps++] = nsldapi_strdup( s ); } rdns[ncomps] = NULL; NSLDAPI_FREE( cpydn ); return( rdns ); }
/* * return a malloc'd copy of "ctrl" (NULL if memory allocation fails) */ static LDAPControl * /* LDAP_CALL */ /* keep this routine internal for now */ ldap_control_dup( LDAPControl *ctrl ) { LDAPControl *rctrl; if (( rctrl = (LDAPControl *)NSLDAPI_MALLOC( sizeof( LDAPControl ))) == NULL ) { return( NULL ); } if ( ldap_control_copy_contents( rctrl, ctrl ) != LDAP_SUCCESS ) { NSLDAPI_FREE( rctrl ); return( NULL ); } return( rctrl ); }
/* * returns an LDAP error code * * XXXmcs: this function used to have #ifdef LDAP_DNS code in it but I * removed it when I improved the parsing (we don't define LDAP_DNS * here at Netscape). */ static int chase_one_referral( LDAP *ld, LDAPRequest *lr, LDAPRequest *origreq, char *refurl, char *desc, int *unknownp ) { int rc, tmprc, secure, msgid; LDAPServer *srv; BerElement *ber; LDAPURLDesc *ludp; *unknownp = 0; ludp = NULLLDAPURLDESC; if ( nsldapi_url_parse( refurl, &ludp, 0 ) != 0 ) { LDAPDebug( LDAP_DEBUG_TRACE, "ignoring unknown %s <%s>\n", desc, refurl, 0 ); *unknownp = 1; rc = LDAP_SUCCESS; goto cleanup_and_return; } secure = (( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 ); /* XXXmcs: can't tell if secure is supported by connect callback */ if ( secure && ld->ld_extconnect_fn == NULL ) { LDAPDebug( LDAP_DEBUG_TRACE, "ignoring LDAPS %s <%s>\n", desc, refurl, 0 ); *unknownp = 1; rc = LDAP_SUCCESS; goto cleanup_and_return; } LDAPDebug( LDAP_DEBUG_TRACE, "chasing LDAP%s %s: <%s>\n", secure ? "S" : "", desc, refurl ); LDAP_MUTEX_LOCK( ld, LDAP_MSGID_LOCK ); msgid = ++ld->ld_msgid; LDAP_MUTEX_UNLOCK( ld, LDAP_MSGID_LOCK ); if (( tmprc = re_encode_request( ld, origreq->lr_ber, msgid, ludp, &ber )) != LDAP_SUCCESS ) { rc = tmprc; goto cleanup_and_return; } if (( srv = (LDAPServer *)NSLDAPI_CALLOC( 1, sizeof( LDAPServer ))) == NULL ) { ber_free( ber, 1 ); rc = LDAP_NO_MEMORY; goto cleanup_and_return; } if (ludp->lud_host == NULL && ld->ld_defhost == NULL) { srv->lsrv_host = NULL; } else { if (ludp->lud_host == NULL) { srv->lsrv_host = nsldapi_strdup( origreq->lr_conn->lconn_server->lsrv_host ); LDAPDebug(LDAP_DEBUG_TRACE, "chase_one_referral: using hostname '%s' from original " "request on new request\n", srv->lsrv_host, 0, 0); } else { srv->lsrv_host = nsldapi_strdup(ludp->lud_host); LDAPDebug(LDAP_DEBUG_TRACE, "chase_one_referral: using hostname '%s' as specified " "on new request\n", srv->lsrv_host, 0, 0); } if (srv->lsrv_host == NULL) { NSLDAPI_FREE((char *)srv); ber_free(ber, 1); rc = LDAP_NO_MEMORY; goto cleanup_and_return; } } /* * According to our reading of RFCs 2255 and 1738, the * following algorithm applies: * - no hostport (no host, no port) provided in LDAP URL, use those * of previous request * - no port but a host, use default LDAP port * - else use given hostport */ if (ludp->lud_port == 0 && ludp->lud_host == NULL) { srv->lsrv_port = origreq->lr_conn->lconn_server->lsrv_port; LDAPDebug(LDAP_DEBUG_TRACE, "chase_one_referral: using port (%d) from original " "request on new request\n", srv->lsrv_port, 0, 0); } else if (ludp->lud_port == 0 && ludp->lud_host != NULL) { srv->lsrv_port = (secure) ? LDAPS_PORT : LDAP_PORT; LDAPDebug(LDAP_DEBUG_TRACE, "chase_one_referral: using default port (%d) \n", srv->lsrv_port, 0, 0); } else { srv->lsrv_port = ludp->lud_port; LDAPDebug(LDAP_DEBUG_TRACE, "chase_one_referral: using port (%d) as specified on " "new request\n", srv->lsrv_port, 0, 0); } if ( secure ) { srv->lsrv_options |= LDAP_SRV_OPT_SECURE; } if ( nsldapi_send_server_request( ld, ber, msgid, lr, srv, NULL, NULL, 1 ) < 0 ) { rc = LDAP_GET_LDERRNO( ld, NULL, NULL ); LDAPDebug( LDAP_DEBUG_ANY, "Unable to chase %s %s (%s)\n", desc, refurl, ldap_err2string( rc )); } else { rc = LDAP_SUCCESS; } cleanup_and_return: if ( ludp != NULLLDAPURLDESC ) { ldap_free_urldesc( ludp ); } return( rc ); }
/* * Initiate chasing of LDAPv2+ (Umich extension) referrals. * * Returns an LDAP error code. * * Note that *hadrefp will be set to 1 if one or more referrals were found in * "*errstrp" (even if we can't chase them) and zero if none were found. * * XXX merging of errors in this routine needs to be improved. */ int nsldapi_chase_v2_referrals( LDAP *ld, LDAPRequest *lr, char **errstrp, int *totalcountp, int *chasingcountp ) { char *p, *ref, *unfollowed; LDAPRequest *origreq; int rc, tmprc, len, unknown; LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_chase_v2_referrals\n", 0, 0, 0 ); *totalcountp = *chasingcountp = 0; if ( *errstrp == NULL ) { return( LDAP_SUCCESS ); } len = strlen( *errstrp ); for ( p = *errstrp; len >= LDAP_REF_STR_LEN; ++p, --len ) { if (( *p == 'R' || *p == 'r' ) && strncasecmp( p, LDAP_REF_STR, LDAP_REF_STR_LEN ) == 0 ) { *p = '\0'; p += LDAP_REF_STR_LEN; break; } } if ( len < LDAP_REF_STR_LEN ) { return( LDAP_SUCCESS ); } if ( lr->lr_parentcnt >= ld->ld_refhoplimit ) { LDAPDebug( LDAP_DEBUG_TRACE, "more than %d referral hops (dropping)\n", ld->ld_refhoplimit, 0, 0 ); return( LDAP_REFERRAL_LIMIT_EXCEEDED ); } /* find original request */ for ( origreq = lr; origreq->lr_parent != NULL; origreq = origreq->lr_parent ) { ; } unfollowed = NULL; rc = LDAP_SUCCESS; /* parse out & follow referrals */ for ( ref = p; rc == LDAP_SUCCESS && ref != NULL; ref = p ) { if (( p = strchr( ref, '\n' )) != NULL ) { *p++ = '\0'; } else { p = NULL; } ++*totalcountp; rc = chase_one_referral( ld, lr, origreq, ref, "v2 referral", &unknown ); if ( rc != LDAP_SUCCESS || unknown ) { if (( tmprc = nsldapi_append_referral( ld, &unfollowed, ref )) != LDAP_SUCCESS ) { rc = tmprc; } } else { ++*chasingcountp; } } NSLDAPI_FREE( *errstrp ); *errstrp = unfollowed; return( rc ); }
LDAPConn * nsldapi_new_connection( LDAP *ld, LDAPServer **srvlistp, int use_ldsb, int connect, int bind ) { int rc; LDAPConn *lc; LDAPServer *prevsrv, *srv; Sockbuf *sb = NULL; /* * make a new LDAP server connection */ if (( lc = (LDAPConn *)NSLDAPI_CALLOC( 1, sizeof( LDAPConn ))) == NULL || ( !use_ldsb && ( sb = ber_sockbuf_alloc()) == NULL )) { if ( lc != NULL ) { NSLDAPI_FREE( (char *)lc ); } LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); return( NULL ); } LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); if ( !use_ldsb ) { /* * we have allocated a new sockbuf * set I/O routines to match those in default LDAP sockbuf */ IFP sb_fn; struct lber_x_ext_io_fns extiofns; extiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; if ( ber_sockbuf_get_option( ld->ld_sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, &extiofns ) == 0 ) { ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_EXT_IO_FNS, &extiofns ); } if ( ber_sockbuf_get_option( ld->ld_sbp, LBER_SOCKBUF_OPT_READ_FN, (void *)&sb_fn ) == 0 && sb_fn != NULL ) { ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_READ_FN, (void *)sb_fn ); } if ( ber_sockbuf_get_option( ld->ld_sbp, LBER_SOCKBUF_OPT_WRITE_FN, (void *)&sb_fn ) == 0 && sb_fn != NULL ) { ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_WRITE_FN, (void *)sb_fn ); } } lc->lconn_sb = ( use_ldsb ) ? ld->ld_sbp : sb; lc->lconn_version = ld->ld_version; /* inherited */ LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); if ( connect ) { prevsrv = NULL; /* * save the return code for later */ for ( srv = *srvlistp; srv != NULL; srv = srv->lsrv_next ) { rc = nsldapi_connect_to_host( ld, lc->lconn_sb, srv->lsrv_host, srv->lsrv_port, ( srv->lsrv_options & LDAP_SRV_OPT_SECURE ) != 0, &lc->lconn_krbinstance ); if (rc != -1) { break; } prevsrv = srv; } if ( srv == NULL ) { if ( !use_ldsb ) { NSLDAPI_FREE( (char *)lc->lconn_sb ); } NSLDAPI_FREE( (char *)lc ); /* nsldapi_open_ldap_connection has already set ld_errno */ return( NULL ); } if ( prevsrv == NULL ) { *srvlistp = srv->lsrv_next; } else { prevsrv->lsrv_next = srv->lsrv_next; } lc->lconn_server = srv; } if (ld->ld_options & LDAP_BITOPT_ASYNC && rc == -2) { lc->lconn_status = LDAP_CONNST_CONNECTING; } else { 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, lderr, freepasswd, authmethod; char *binddn, *passwd; LDAPConn *savedefconn; freepasswd = err = 0; if ( ld->ld_rebind_fn == NULL ) { binddn = passwd = ""; authmethod = LDAP_AUTH_SIMPLE; } else { if (( lderr = (*ld->ld_rebind_fn)( ld, &binddn, &passwd, &authmethod, 0, ld->ld_rebind_arg )) == LDAP_SUCCESS ) { freepasswd = 1; } else { LDAP_SET_LDERRNO( ld, lderr, NULL, NULL ); err = -1; } } if ( err == 0 ) { savedefconn = ld->ld_defconn; ld->ld_defconn = lc; ++lc->lconn_refcnt; /* avoid premature free */ /* * when binding, we will back down as low as LDAPv2 * if we get back "protocol error" from bind attempts */ for ( ;; ) { /* LDAP_MUTEX_UNLOCK(ld, LDAP_CONN_LOCK); */ if (( lderr = ldap_bind_s( ld, binddn, passwd, authmethod )) == LDAP_SUCCESS ) { /* LDAP_MUTEX_LOCK(ld, LDAP_CONN_LOCK); */ break; } /* LDAP_MUTEX_LOCK(ld, LDAP_CONN_LOCK); */ if ( lc->lconn_version <= LDAP_VERSION2 || lderr != LDAP_PROTOCOL_ERROR ) { err = -1; break; } --lc->lconn_version; /* try lower version */ } --lc->lconn_refcnt; ld->ld_defconn = savedefconn; } if ( freepasswd ) { (*ld->ld_rebind_fn)( ld, &binddn, &passwd, &authmethod, 1, ld->ld_rebind_arg ); } if ( err != 0 ) { nsldapi_free_connection( ld, lc, NULL, NULL, 1, 0 ); lc = NULL; } } return( lc ); }
/* returns the message id of the request or -1 if an error occurs */ int nsldapi_send_server_request( LDAP *ld, /* session handle */ BerElement *ber, /* message to send */ int msgid, /* ID of message to send */ LDAPRequest *parentreq, /* non-NULL for referred requests */ LDAPServer *srvlist, /* servers to connect to (NULL for default) */ LDAPConn *lc, /* connection to use (NULL for default) */ char *bindreqdn, /* non-NULL for bind requests */ int bind /* perform a bind after opening new conn.? */ ) { LDAPRequest *lr; int err; int incparent; /* did we bump parent's ref count? */ LDAPDebug( LDAP_DEBUG_TRACE, "nsldapi_send_server_request\n", 0, 0, 0 ); incparent = 0; LDAP_MUTEX_LOCK( ld, LDAP_CONN_LOCK ); if ( lc == NULL ) { if ( srvlist == NULL ) { if ( ld->ld_defconn == NULL ) { LDAP_MUTEX_LOCK( ld, LDAP_OPTION_LOCK ); if ( bindreqdn == NULL && ( ld->ld_options & LDAP_BITOPT_RECONNECT ) != 0 ) { LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); ber_free( ber, 1 ); LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); return( -1 ); } LDAP_MUTEX_UNLOCK( ld, LDAP_OPTION_LOCK ); if ( nsldapi_open_ldap_defconn( ld ) < 0 ) { ber_free( ber, 1 ); LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); return( -1 ); } } lc = ld->ld_defconn; } else { if (( lc = find_connection( ld, srvlist, 1 )) == NULL ) { if ( bind && (parentreq != NULL) ) { /* Remember the bind in the parent */ incparent = 1; ++parentreq->lr_outrefcnt; } lc = nsldapi_new_connection( ld, &srvlist, 0, 1, bind ); } free_servers( srvlist ); } } /* * the logic here is: * if * 1. no connections exists, * or * 2. if the connection is either not in the connected * or connecting state in an async io model * or * 3. the connection is notin a connected state with normal (non async io) */ if ( lc == NULL || ( (ld->ld_options & LDAP_BITOPT_ASYNC && lc->lconn_status != LDAP_CONNST_CONNECTING && lc->lconn_status != LDAP_CONNST_CONNECTED) || (!(ld->ld_options & LDAP_BITOPT_ASYNC ) && lc->lconn_status != LDAP_CONNST_CONNECTED) ) ) { ber_free( ber, 1 ); if ( lc != NULL ) { LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); } if ( incparent ) { /* Forget about the bind */ --parentreq->lr_outrefcnt; } LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); return( -1 ); } use_connection( ld, lc ); if (( lr = (LDAPRequest *)NSLDAPI_CALLOC( 1, sizeof( LDAPRequest ))) == NULL || ( bindreqdn != NULL && ( bindreqdn = nsldapi_strdup( bindreqdn )) == NULL )) { if ( lr != NULL ) { NSLDAPI_FREE( lr ); } LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL ); nsldapi_free_connection( ld, lc, NULL, NULL, 0, 0 ); ber_free( ber, 1 ); if ( incparent ) { /* Forget about the bind */ --parentreq->lr_outrefcnt; } LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); return( -1 ); } lr->lr_binddn = bindreqdn; 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 + 1; lr->lr_parent = parentreq; if ( parentreq->lr_child != NULL ) { lr->lr_sibling = parentreq->lr_child; } parentreq->lr_child = lr; } else { /* original request */ lr->lr_origid = lr->lr_msgid; } LDAP_MUTEX_LOCK( ld, LDAP_REQ_LOCK ); if (( lr->lr_next = ld->ld_requests ) != NULL ) { lr->lr_next->lr_prev = lr; } ld->ld_requests = lr; lr->lr_prev = NULL; if (( err = nsldapi_ber_flush( ld, lc->lconn_sb, ber, 0, 1 )) != 0 ) { /* need to continue write later */ if (ld->ld_options & LDAP_BITOPT_ASYNC && err == -2 ) { lr->lr_status = LDAP_REQST_WRITING; nsldapi_iostatus_interest_write( ld, lc->lconn_sb ); } else { LDAP_SET_LDERRNO( ld, LDAP_SERVER_DOWN, NULL, NULL ); nsldapi_free_request( ld, lr, 0 ); nsldapi_free_connection( ld, lc, NULL, NULL, 0, 0 ); LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); return( -1 ); } } else { if ( parentreq == NULL ) { ber->ber_end = ber->ber_ptr; ber->ber_ptr = ber->ber_buf; } /* sent -- waiting for a response */ if (ld->ld_options & LDAP_BITOPT_ASYNC) { lc->lconn_status = LDAP_CONNST_CONNECTED; } nsldapi_iostatus_interest_read( ld, lc->lconn_sb ); } LDAP_MUTEX_UNLOCK( ld, LDAP_REQ_LOCK ); LDAP_MUTEX_UNLOCK( ld, LDAP_CONN_LOCK ); LDAP_SET_LDERRNO( ld, LDAP_SUCCESS, NULL, NULL ); 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 ); }
/* * Pull the oid returned by the server and the data out of an extended * operation result. Return an LDAP error code. */ int LDAP_CALL ldap_parse_extended_result( LDAP *ld, LDAPMessage *res, char **retoidp, /* may be NULL */ struct berval **retdatap, /* may be NULL */ int freeit ) { struct berelement ber; unsigned long len; long err; char *m, *e, *roid; struct berval *rdata; LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_extended_result\n", 0, 0, 0 ); if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) { return( LDAP_PARAM_ERROR ); } if ( !NSLDAPI_VALID_LDAPMESSAGE_EXRESULT_POINTER( res )) { return( LDAP_PARAM_ERROR ); } m = e = NULL; ber = *(res->lm_ber); if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION3 ) { LDAP_SET_LDERRNO( ld, LDAP_NOT_SUPPORTED, NULL, NULL ); return( LDAP_NOT_SUPPORTED ); } if ( ber_scanf( &ber, "{iaa", &err, &m, &e ) == LBER_ERROR ) { goto decoding_error; } roid = NULL; if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_EXOP_RES_OID ) { if ( ber_scanf( &ber, "a", &roid ) == LBER_ERROR ) { goto decoding_error; } } if ( retoidp != NULL ) { *retoidp = roid; } else if ( roid != NULL ) { NSLDAPI_FREE( roid ); } rdata = NULL; if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_EXOP_RES_VALUE ) { if ( ber_scanf( &ber, "O", &rdata ) == LBER_ERROR ) { goto decoding_error; } } if ( retdatap != NULL ) { *retdatap = rdata; } else if ( rdata != NULL ) { ber_bvfree( rdata ); } LDAP_SET_LDERRNO( ld, err, m, e ); if ( freeit ) { ldap_msgfree( res ); } return( LDAP_SUCCESS ); decoding_error:; LDAP_SET_LDERRNO( ld, LDAP_DECODING_ERROR, NULL, NULL ); return( LDAP_DECODING_ERROR ); }
static int parse_subtypes( const char *target, int *baseLenp, char **langp, _SubStringIndex **subs, int *nsubtypes ) { int nSubtypes = 0; int ind = 0; char *nextToken; _SubStringIndex *result = NULL; int langIndex; int targetLen; int subtypeStart; langIndex = LANG_SUBTYPE_INDEX_NONE; *subs = NULL; *langp = NULL; *baseLenp = 0; *nsubtypes = 0; targetLen = strlen( target ); /* Parse past base attribute */ nextToken = strchr( target, ';' ); if ( NULL != nextToken ) { subtypeStart = nextToken - target + 1; *baseLenp = subtypeStart - 1; } else { subtypeStart = targetLen; *baseLenp = subtypeStart; } ind = subtypeStart; /* How many subtypes? */ nextToken = (char *)target + subtypeStart; while ( nextToken && *nextToken ) { char *thisToken = nextToken; nextToken = strchr( thisToken, ';' ); if ( NULL != nextToken ) nextToken++; if ( 0 == strncasecmp( thisToken, "lang-", 5 ) ) { /* If there was a previous lang tag, this is illegal! */ if ( langIndex != LANG_SUBTYPE_INDEX_NONE ) { langIndex = LANG_SUBTYPE_INDEX_DUPLICATE; return langIndex; } else { langIndex = nSubtypes; } } else { nSubtypes++; } } /* No language subtype? */ if ( langIndex < 0 ) return langIndex; /* Allocate array of non-language subtypes */ if ( nSubtypes > 0 ) { result = (_SubStringIndex *)NSLDAPI_MALLOC( sizeof(*result) * nSubtypes ); if (result == NULL) { return LANG_SUBTYPE_INDEX_NONE; /* Error */ } memset( result, 0, sizeof(*result) * nSubtypes ); } ind = 0; nSubtypes = 0; ind = subtypeStart; nextToken = (char *)target + subtypeStart; while ( nextToken && *nextToken ) { char *thisToken = nextToken; int len; nextToken = strchr( thisToken, ';' ); if ( NULL != nextToken ) { len = nextToken - thisToken; nextToken++; } else { nextToken = (char *)target + targetLen; len = nextToken - thisToken; } if ( 0 == strncasecmp( thisToken, "lang-", 5 ) ) { int i; *langp = (char *)NSLDAPI_MALLOC( len + 1 ); if (*langp == NULL) { if (result != NULL) NSLDAPI_FREE(result); return LANG_SUBTYPE_INDEX_NONE; /* Error */ } for( i = 0; i < len; i++ ) (*langp)[i] = toupper( target[ind+i] ); (*langp)[len] = 0; } else { result[nSubtypes].start = thisToken - target; result[nSubtypes].length = len; nSubtypes++; } } *subs = result; *nsubtypes = nSubtypes; return langIndex; }
LDAP_CALL ldap_init( const char *defhost, int defport ) { LDAP *ld; if ( !nsldapi_initialized ) { nsldapi_initialize_defaults(); } if ( defport < 0 || defport > LDAP_PORT_MAX ) { LDAPDebug( LDAP_DEBUG_ANY, "ldap_init: port %d is invalid (port numbers must range from 1 to %d)\n", defport, LDAP_PORT_MAX, 0 ); #if !defined( macintosh ) && !defined( DOS ) errno = EINVAL; #endif return( NULL ); } LDAPDebug( LDAP_DEBUG_TRACE, "ldap_init\n", 0, 0, 0 ); if ( (ld = (LDAP*)NSLDAPI_MALLOC( sizeof(struct ldap) )) == NULL ) { return( NULL ); } /* copy defaults */ SAFEMEMCPY( ld, &nsldapi_ld_defaults, sizeof( struct ldap )); if ( nsldapi_ld_defaults.ld_io_fns_ptr != NULL ) { if (( ld->ld_io_fns_ptr = (struct ldap_io_fns *)NSLDAPI_MALLOC( sizeof( struct ldap_io_fns ))) == NULL ) { NSLDAPI_FREE( (char *)ld ); return( NULL ); } /* struct copy */ *(ld->ld_io_fns_ptr) = *(nsldapi_ld_defaults.ld_io_fns_ptr); } /* call the new handle I/O callback if one is defined */ if ( ld->ld_extnewhandle_fn != NULL ) { /* * We always pass the session extended I/O argument to * the new handle callback. */ if ( ld->ld_extnewhandle_fn( ld, ld->ld_ext_session_arg ) != LDAP_SUCCESS ) { NSLDAPI_FREE( (char*)ld ); return( NULL ); } } /* allocate session-specific resources */ if (( ld->ld_sbp = ber_sockbuf_alloc()) == NULL || ( defhost != NULL && ( ld->ld_defhost = nsldapi_strdup( defhost )) == NULL ) || ((ld->ld_mutex = (void **) NSLDAPI_CALLOC( LDAP_MAX_LOCK, sizeof(void *))) == NULL )) { if ( ld->ld_sbp != NULL ) { ber_sockbuf_free( ld->ld_sbp ); } if( ld->ld_mutex != NULL ) { NSLDAPI_FREE( ld->ld_mutex ); } NSLDAPI_FREE( (char*)ld ); return( NULL ); } /* install Sockbuf I/O functions if set in LDAP * */ if ( ld->ld_extread_fn != NULL || ld->ld_extwrite_fn != NULL ) { struct lber_x_ext_io_fns lberiofns; memset( &lberiofns, 0, sizeof( lberiofns )); lberiofns.lbextiofn_size = LBER_X_EXTIO_FNS_SIZE; lberiofns.lbextiofn_read = ld->ld_extread_fn; lberiofns.lbextiofn_write = ld->ld_extwrite_fn; lberiofns.lbextiofn_writev = ld->ld_extwritev_fn; lberiofns.lbextiofn_socket_arg = NULL; ber_sockbuf_set_option( ld->ld_sbp, LBER_SOCKBUF_OPT_EXT_IO_FNS, (void *)&lberiofns ); } #ifdef _SOLARIS_SDK /* Install the functions for IPv6 support */ /* code sequencing is critical from here to nsldapi_mutex_alloc_all */ if ( prldap_install_thread_functions( ld, 1 ) != 0 || prldap_install_io_functions( ld, 1 ) != 0 || prldap_install_dns_functions( ld ) != 0 ) { /* go through ld and free resources */ ldap_unbind( ld ); ld = NULL; return( NULL ); } #else /* allocate mutexes */ nsldapi_mutex_alloc_all( ld ); #endif /* set default port */ ld->ld_defport = ( defport == 0 ) ? LDAP_PORT : defport; return( ld ); }
static int check_lang_match( const char *target, const char *baseTarget, _SubStringIndex *targetTypes, int ntargetTypes, char *targetLang, char *attr ) { int langIndex; _SubStringIndex *subtypes; int baseLen; char *lang; int nsubtypes; int mismatch = 0; int match = -1; int i; /* Get all subtypes in the attribute name */ langIndex = parse_subtypes( attr, &baseLen, &lang, &subtypes, &nsubtypes ); /* Check if there any required non-language subtypes which are not in this attribute */ for( i = 0; i < ntargetTypes; i++ ) { char *t = (char *)target+targetTypes[i].start; int tlen = targetTypes[i].length; int j; for( j = 0; j < nsubtypes; j++ ) { char *a = attr + subtypes[j].start; int alen = subtypes[j].length; if ( (tlen == alen) && !strncasecmp( t, a, tlen ) ) break; } if ( j >= nsubtypes ) { mismatch = 1; break; } } if ( mismatch ) { if ( NULL != subtypes ) NSLDAPI_FREE( subtypes ); if ( NULL != lang ) NSLDAPI_FREE( lang ); return -1; } /* If there was no language subtype... */ if ( langIndex < 0 ) { if ( NULL != subtypes ) NSLDAPI_FREE( subtypes ); if ( NULL != lang ) NSLDAPI_FREE( lang ); if ( LANG_SUBTYPE_INDEX_NONE == langIndex ) return 0; else return -1; } /* Okay, now check the language subtag */ i = 0; while( targetLang[i] && lang[i] && (toupper(targetLang[i]) == toupper(lang[i])) ) i++; /* The total length can't be longer than the requested subtype */ if ( !lang[i] || (lang[i] == ';') ) { /* If the found subtype is shorter than the requested one, the next character in the requested one should be "-" */ if ( !targetLang[i] || (targetLang[i] == '-') ) match = i; } return match; }
int nsldapi_sasl_secprops( const char *in, sasl_security_properties_t *secprops ) { int i; char **props = NULL; char *inp; unsigned sflags = 0; sasl_ssf_t max_ssf = 0; sasl_ssf_t min_ssf = 0; unsigned maxbufsize = 0; int got_sflags = 0; int got_max_ssf = 0; int got_min_ssf = 0; int got_maxbufsize = 0; if (in == NULL) { return LDAP_PARAM_ERROR; } inp = nsldapi_strdup(in); if (inp == NULL) { return LDAP_PARAM_ERROR; } props = ldap_str2charray( inp, "," ); NSLDAPI_FREE( inp ); if( props == NULL || secprops == NULL ) { return LDAP_PARAM_ERROR; } for( i=0; props[i]; i++ ) { if( strcasecmp(props[i], "none") == 0 ) { got_sflags++; } else if( strcasecmp(props[i], "noactive") == 0 ) { got_sflags++; sflags |= SASL_SEC_NOACTIVE; } else if( strcasecmp(props[i], "noanonymous") == 0 ) { got_sflags++; sflags |= SASL_SEC_NOANONYMOUS; } else if( strcasecmp(props[i], "nodict") == 0 ) { got_sflags++; sflags |= SASL_SEC_NODICTIONARY; } else if( strcasecmp(props[i], "noplain") == 0 ) { got_sflags++; sflags |= SASL_SEC_NOPLAINTEXT; } else if( strcasecmp(props[i], "forwardsec") == 0 ) { got_sflags++; sflags |= SASL_SEC_FORWARD_SECRECY; } else if( strcasecmp(props[i], "passcred") == 0 ) { got_sflags++; sflags |= SASL_SEC_PASS_CREDENTIALS; } else if( strncasecmp(props[i], "minssf=", sizeof("minssf")) == 0 ) { if( isdigit( props[i][sizeof("minssf")] ) ) { got_min_ssf++; min_ssf = atoi( &props[i][sizeof("minssf")] ); } else { return LDAP_NOT_SUPPORTED; } } else if( strncasecmp(props[i], "maxssf=", sizeof("maxssf")) == 0 ) { if( isdigit( props[i][sizeof("maxssf")] ) ) { got_max_ssf++; max_ssf = atoi( &props[i][sizeof("maxssf")] ); } else { return LDAP_NOT_SUPPORTED; } } else if( strncasecmp(props[i], "maxbufsize=", sizeof("maxbufsize")) == 0 ) { if( isdigit( props[i][sizeof("maxbufsize")] ) ) { got_maxbufsize++; maxbufsize = atoi( &props[i][sizeof("maxbufsize")] ); if( maxbufsize && (( maxbufsize < SASL_MIN_BUFF_SIZE ) || (maxbufsize > SASL_MAX_BUFF_SIZE ))) { return( LDAP_PARAM_ERROR ); } } else { return( LDAP_NOT_SUPPORTED ); } } else { return( LDAP_NOT_SUPPORTED ); } } if(got_sflags) { secprops->security_flags = sflags; } if(got_min_ssf) { secprops->min_ssf = min_ssf; } if(got_max_ssf) { secprops->max_ssf = max_ssf; } if(got_maxbufsize) { secprops->maxbufsize = maxbufsize; } ldap_charray_free( props ); return( LDAP_SUCCESS ); }