Back to index

lightning-sunbird  0.9+nobinonly
error.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Communicator client code, released
00015  * March 31, 1998.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #include "ldap-int.h"
00038 
00039 struct ldaperror {
00040        int    e_code;
00041        char   *e_reason;
00042 };
00043 
00044 static struct ldaperror ldap_errlist[] = {
00045        { LDAP_SUCCESS,                    "Success" },
00046        { LDAP_OPERATIONS_ERROR,           "Operations error" },
00047        { LDAP_PROTOCOL_ERROR,                    "Protocol error" },
00048        { LDAP_TIMELIMIT_EXCEEDED,         "Timelimit exceeded" },
00049        { LDAP_SIZELIMIT_EXCEEDED,         "Sizelimit exceeded" },
00050        { LDAP_COMPARE_FALSE,                     "Compare false" },
00051        { LDAP_COMPARE_TRUE,                      "Compare true" },
00052        { LDAP_STRONG_AUTH_NOT_SUPPORTED,  "Authentication method not supported" },
00053        { LDAP_STRONG_AUTH_REQUIRED,              "Strong authentication required" },
00054        { LDAP_PARTIAL_RESULTS,            "Partial results and referral received" },
00055        { LDAP_REFERRAL,                   "Referral received" },
00056        { LDAP_ADMINLIMIT_EXCEEDED,        "Administrative limit exceeded" },
00057        { LDAP_UNAVAILABLE_CRITICAL_EXTENSION,    "Unavailable critical extension" },
00058        { LDAP_CONFIDENTIALITY_REQUIRED,   "Confidentiality required" },
00059        { LDAP_SASL_BIND_IN_PROGRESS,             "SASL bind in progress" },
00060 
00061        { LDAP_NO_SUCH_ATTRIBUTE,          "No such attribute" },
00062        { LDAP_UNDEFINED_TYPE,                    "Undefined attribute type" },
00063        { LDAP_INAPPROPRIATE_MATCHING,            "Inappropriate matching" },
00064        { LDAP_CONSTRAINT_VIOLATION,              "Constraint violation" },
00065        { LDAP_TYPE_OR_VALUE_EXISTS,              "Type or value exists" },
00066        { LDAP_INVALID_SYNTAX,                    "Invalid syntax" },
00067 
00068        { LDAP_NO_SUCH_OBJECT,                    "No such object" },
00069        { LDAP_ALIAS_PROBLEM,                     "Alias problem" },
00070        { LDAP_INVALID_DN_SYNTAX,          "Invalid DN syntax" },
00071        { LDAP_IS_LEAF,                    "Object is a leaf" },
00072        { LDAP_ALIAS_DEREF_PROBLEM,               "Alias dereferencing problem" },
00073 
00074        { LDAP_INAPPROPRIATE_AUTH,         "Inappropriate authentication" },
00075        { LDAP_INVALID_CREDENTIALS,               "Invalid credentials" },
00076        { LDAP_INSUFFICIENT_ACCESS,               "Insufficient access" },
00077        { LDAP_BUSY,                       "DSA is busy" },
00078        { LDAP_UNAVAILABLE,                "DSA is unavailable" },
00079        { LDAP_UNWILLING_TO_PERFORM,              "DSA is unwilling to perform" },
00080        { LDAP_LOOP_DETECT,                "Loop detected" },
00081     { LDAP_SORT_CONTROL_MISSING,    "Sort Control is missing"  },
00082     { LDAP_INDEX_RANGE_ERROR,              "Search results exceed the range specified by the offsets" }, 
00083     
00084     { LDAP_NAMING_VIOLATION,              "Naming violation" },
00085        { LDAP_OBJECT_CLASS_VIOLATION,            "Object class violation" },
00086        { LDAP_NOT_ALLOWED_ON_NONLEAF,            "Operation not allowed on nonleaf" },
00087        { LDAP_NOT_ALLOWED_ON_RDN,         "Operation not allowed on RDN" },
00088        { LDAP_ALREADY_EXISTS,                    "Already exists" },
00089        { LDAP_NO_OBJECT_CLASS_MODS,              "Cannot modify object class" },
00090        { LDAP_RESULTS_TOO_LARGE,          "Results too large" },
00091        { LDAP_AFFECTS_MULTIPLE_DSAS,             "Affects multiple servers" },
00092 
00093        { LDAP_OTHER,                             "Unknown error" },
00094        { LDAP_SERVER_DOWN,                "Can't contact LDAP server" },
00095        { LDAP_LOCAL_ERROR,                "Local error" },
00096        { LDAP_ENCODING_ERROR,                    "Encoding error" },
00097        { LDAP_DECODING_ERROR,                    "Decoding error" },
00098        { LDAP_TIMEOUT,                           "Timed out" },
00099        { LDAP_AUTH_UNKNOWN,               "Unknown authentication method" },
00100        { LDAP_FILTER_ERROR,               "Bad search filter" },
00101        { LDAP_USER_CANCELLED,                    "User cancelled operation" },
00102        { LDAP_PARAM_ERROR,                "Bad parameter to an ldap routine" },
00103        { LDAP_NO_MEMORY,                  "Out of memory" },
00104        { LDAP_CONNECT_ERROR,                     "Can't connect to the LDAP server" },
00105        { LDAP_NOT_SUPPORTED,                     "Not supported by this version of the LDAP protocol" },
00106        { LDAP_CONTROL_NOT_FOUND,          "Requested LDAP control not found" },
00107        { LDAP_NO_RESULTS_RETURNED,        "No results returned" },
00108        { LDAP_MORE_RESULTS_TO_RETURN,            "More results to return" },
00109        { LDAP_CLIENT_LOOP,                "Client detected loop" },
00110        { LDAP_REFERRAL_LIMIT_EXCEEDED,           "Referral hop limit exceeded" },
00111        { -1, 0 }
00112 };
00113 
00114 char *
00115 LDAP_CALL
00116 ldap_err2string( int err )
00117 {
00118        int    i;
00119 
00120        LDAPDebug( LDAP_DEBUG_TRACE, "ldap_err2string\n", 0, 0, 0 );
00121 
00122        for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) {
00123               if ( err == ldap_errlist[i].e_code )
00124                      return( ldap_errlist[i].e_reason );
00125        }
00126 
00127        return( "Unknown error" );
00128 }
00129 
00130 
00131 static char *
00132 nsldapi_safe_strerror( e )
00133 {
00134        char *s;
00135 
00136        if (( s = strerror( e )) == NULL ) {
00137               s = "unknown error";
00138        }
00139 
00140        return( s );
00141 }
00142 
00143 
00144 void
00145 LDAP_CALL
00146 ldap_perror( LDAP *ld, const char *s )
00147 {
00148        int    i, err;
00149        char   *matched, *errmsg, *separator;
00150        char    msg[1024];
00151 
00152        LDAPDebug( LDAP_DEBUG_TRACE, "ldap_perror\n", 0, 0, 0 );
00153 
00154        if ( s == NULL ) {
00155               s = separator = "";
00156        } else {
00157               separator = ": ";
00158        }
00159 
00160        if ( ld == NULL ) {
00161               sprintf( msg, "%s%s%s", s, separator,
00162                   nsldapi_safe_strerror( errno ) );
00163               ber_err_print( msg );
00164               return;
00165        }
00166 
00167        LDAP_MUTEX_LOCK( ld, LDAP_ERR_LOCK );
00168        err = LDAP_GET_LDERRNO( ld, &matched, &errmsg );
00169        for ( i = 0; ldap_errlist[i].e_code != -1; i++ ) {
00170               if ( err == ldap_errlist[i].e_code ) {
00171                      sprintf( msg, "%s%s%s", s, separator,
00172                                 ldap_errlist[i].e_reason );
00173                      ber_err_print( msg );
00174                      if ( err == LDAP_CONNECT_ERROR ) {
00175                             ber_err_print( " - " );
00176                             ber_err_print( nsldapi_safe_strerror(
00177                                 LDAP_GET_ERRNO( ld )));
00178                      }
00179                      ber_err_print( "\n" );
00180                      if ( matched != NULL && *matched != '\0' ) {
00181                             sprintf( msg, "%s%smatched: %s\n",
00182                                 s, separator, matched );
00183                             ber_err_print( msg );
00184                      }
00185                      if ( errmsg != NULL && *errmsg != '\0' ) {
00186                             sprintf( msg, "%s%sadditional info: %s\n",
00187                                 s, separator, errmsg );
00188                             ber_err_print( msg );
00189                      }
00190                      LDAP_MUTEX_UNLOCK( ld, LDAP_ERR_LOCK );
00191                      return;
00192               }
00193        }
00194        sprintf( msg, "%s%sNot an LDAP errno %d\n", s, separator, err );
00195        ber_err_print( msg );
00196        LDAP_MUTEX_UNLOCK( ld, LDAP_ERR_LOCK );
00197 }
00198 
00199 int
00200 LDAP_CALL
00201 ldap_result2error( LDAP *ld, LDAPMessage *r, int freeit )
00202 {
00203        int    lderr_parse, lderr;
00204 
00205        lderr_parse = ldap_parse_result( ld, r, &lderr, NULL, NULL, NULL,
00206            NULL, freeit );
00207 
00208        if ( lderr_parse != LDAP_SUCCESS ) {
00209               return( lderr_parse );
00210        }
00211 
00212        return( lderr );
00213 }
00214 
00215 int
00216 LDAP_CALL
00217 ldap_get_lderrno( LDAP *ld, char **m, char **s )
00218 {
00219        if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
00220               return( LDAP_PARAM_ERROR ); /* punt */
00221        }
00222 
00223        if ( ld->ld_get_lderrno_fn == NULL ) {
00224               if ( m != NULL ) {
00225                      *m = ld->ld_matched;
00226               }
00227               if ( s != NULL ) {
00228                      *s = ld->ld_error;
00229               }
00230               return( ld->ld_errno );
00231        } else {
00232               return( ld->ld_get_lderrno_fn( m, s, ld->ld_lderrno_arg ) );
00233        }
00234 }
00235 
00236 
00237 /*
00238  * Note: there is no need for callers of ldap_set_lderrno() to lock the
00239  * ld mutex.  If applications intend to share an LDAP session handle
00240  * between threads they *must* perform their own locking around the
00241  * session handle or they must install a "set lderrno" thread callback
00242  * function.
00243  * 
00244  */
00245 int
00246 LDAP_CALL
00247 ldap_set_lderrno( LDAP *ld, int e, char *m, char *s )
00248 {
00249        if ( !NSLDAPI_VALID_LDAP_POINTER( ld )) {
00250               return( LDAP_PARAM_ERROR );
00251        }
00252 
00253        if ( ld->ld_set_lderrno_fn != NULL ) {
00254               ld->ld_set_lderrno_fn( e, m, s, ld->ld_lderrno_arg );
00255        } else {
00256         LDAP_MUTEX_LOCK( ld, LDAP_ERR_LOCK );
00257               ld->ld_errno = e;
00258               if ( ld->ld_matched ) {
00259                      NSLDAPI_FREE( ld->ld_matched );
00260               }
00261               ld->ld_matched = m;
00262               if ( ld->ld_error ) {
00263                      NSLDAPI_FREE( ld->ld_error );
00264               }
00265               ld->ld_error = s;
00266         LDAP_MUTEX_UNLOCK( ld, LDAP_ERR_LOCK );
00267        }
00268 
00269        return( LDAP_SUCCESS );
00270 }
00271 
00272 
00273 /*
00274  * Returns an LDAP error that says whether parse succeeded.  The error code
00275  * from the LDAP result itself is returned in the errcodep result parameter.
00276  * If any of the result params. (errcodep, matchednp, errmsgp, referralsp,
00277  * or serverctrlsp) are NULL we don't return that info.
00278  */
00279 int
00280 LDAP_CALL
00281 ldap_parse_result( LDAP *ld, LDAPMessage *res, int *errcodep, char **matchednp,
00282        char **errmsgp, char ***referralsp, LDAPControl ***serverctrlsp,
00283        int freeit )
00284 {
00285        LDAPMessage          *lm;
00286        int                  err, errcode;
00287        char                 *m, *e;
00288 
00289        LDAPDebug( LDAP_DEBUG_TRACE, "ldap_parse_result\n", 0, 0, 0 );
00290 
00291        if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) ||
00292            !NSLDAPI_VALID_LDAPMESSAGE_POINTER( res )) {
00293               return( LDAP_PARAM_ERROR );
00294        }
00295 
00296        /* skip over entries and references to find next result in this chain */
00297        for ( lm = res; lm != NULL; lm = lm->lm_chain ) {       
00298               if ( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY &&
00299                   lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) {
00300                      break;
00301               }
00302        }
00303 
00304        if ( lm == NULL ) {
00305               err = LDAP_NO_RESULTS_RETURNED;
00306               LDAP_SET_LDERRNO( ld, err, NULL, NULL );
00307               return( err );
00308        }
00309 
00310        err = nsldapi_parse_result( ld, lm->lm_msgtype, lm->lm_ber, &errcode,
00311            &m, &e, referralsp, serverctrlsp );
00312 
00313        if ( err == LDAP_SUCCESS ) {
00314               if ( errcodep != NULL ) {
00315                      *errcodep = errcode;
00316               }
00317               if ( matchednp != NULL ) {
00318                      *matchednp = nsldapi_strdup( m );
00319               }
00320               if ( errmsgp != NULL ) {
00321                      *errmsgp = nsldapi_strdup( e );
00322               }
00323 
00324               /*
00325                * if there are more result messages in the chain, arrange to
00326                * return the special LDAP_MORE_RESULTS_TO_RETURN "error" code.
00327                */
00328               for ( lm = lm->lm_chain; lm != NULL; lm = lm->lm_chain ) {     
00329                      if ( lm->lm_msgtype != LDAP_RES_SEARCH_ENTRY &&
00330                          lm->lm_msgtype != LDAP_RES_SEARCH_REFERENCE ) {
00331                             err = LDAP_MORE_RESULTS_TO_RETURN;
00332                             break;
00333                      }
00334               }
00335        } else {
00336               m = e = NULL;
00337        }
00338 
00339        if ( freeit ) {
00340               ldap_msgfree( res );
00341        }
00342 
00343        LDAP_SET_LDERRNO( ld, ( err == LDAP_SUCCESS ) ? errcode : err, m, e );
00344 
00345        return( err );
00346 }
00347 
00348 
00349 /*
00350  * returns an LDAP error code indicating success or failure of parsing
00351  * does NOT set any error information inside "ld"
00352  */
00353 int
00354 nsldapi_parse_result( LDAP *ld, int msgtype, BerElement *rber, int *errcodep,
00355     char **matchednp, char **errmsgp, char ***referralsp,
00356     LDAPControl ***serverctrlsp )
00357 {
00358        BerElement    ber;
00359        unsigned long len;
00360        int           berrc, err, errcode;
00361        long          along;
00362        char          *m, *e;
00363 
00364        /*
00365         * Parse the result message.  LDAPv3 result messages look like this:
00366         *
00367         *     LDAPResult ::= SEQUENCE {
00368         *            resultCode    ENUMERATED { ... },
00369         *            matchedDN     LDAPDN,
00370         *            errorMessage  LDAPString,
00371         *            referral      [3] Referral OPTIONAL
00372         *            opSpecificStuff      OPTIONAL
00373         *     }
00374         *
00375         * all wrapped up in an LDAPMessage sequence which looks like this:
00376         *     LDAPMessage ::= SEQUENCE {
00377         *            messageID     MessageID,
00378         *            LDAPResult    CHOICE { ... },      // message type
00379         *            controls      [0] Controls OPTIONAL
00380         *     }
00381         *
00382         * LDAPv2 messages don't include referrals or controls.
00383         * LDAPv1 messages don't include matchedDN, referrals, or controls.
00384         *
00385         * ldap_result() pulls out the message id, so by the time a result
00386         * message gets here we are sitting at the start of the LDAPResult.
00387         */
00388 
00389        err = LDAP_SUCCESS;  /* optimistic */
00390        m = e = NULL;
00391        if ( matchednp != NULL ) {
00392               *matchednp = NULL;
00393        }
00394        if ( errmsgp != NULL ) {
00395               *errmsgp = NULL;
00396        }
00397        if ( referralsp != NULL ) {
00398               *referralsp = NULL;
00399        }
00400        if ( serverctrlsp != NULL ) {
00401               *serverctrlsp = NULL;
00402        }
00403        ber = *rber;         /* struct copy */
00404 
00405        if ( NSLDAPI_LDAP_VERSION( ld ) < LDAP_VERSION2 ) {
00406               berrc = ber_scanf( &ber, "{ia}", &along, &e );
00407               errcode = (int)along;       /* XXX lossy cast */
00408        } else {
00409               if (( berrc = ber_scanf( &ber, "{iaa", &along, &m, &e ))
00410                   != LBER_ERROR ) {
00411                      errcode = (int)along;       /* XXX lossy cast */
00412                      /* check for optional referrals */
00413                      if ( ber_peek_tag( &ber, &len ) == LDAP_TAG_REFERRAL ) {
00414                             if ( referralsp == NULL ) {
00415                                    /* skip referrals */
00416                                    berrc = ber_scanf( &ber, "x" );
00417                             } else {
00418                                    /* suck out referrals */
00419                                    berrc = ber_scanf( &ber, "v",
00420                                        referralsp );
00421                             }
00422                      } else if ( referralsp != NULL ) {
00423                             *referralsp = NULL;
00424                      }
00425               }
00426 
00427               if ( berrc != LBER_ERROR ) {
00428                      /*
00429                       * skip past optional operation-specific elements:
00430                       *   bind results - serverSASLcreds
00431                       *   extendedop results -  OID plus value
00432                       */
00433                      if ( msgtype == LDAP_RES_BIND ) {
00434                             if ( ber_peek_tag( &ber, &len ) == 
00435                                 LDAP_TAG_SASL_RES_CREDS ) {
00436                                    berrc = ber_scanf( &ber, "x" );
00437                             }
00438                      } else if ( msgtype == LDAP_RES_EXTENDED ) {
00439                             if ( ber_peek_tag( &ber, &len ) ==
00440                                 LDAP_TAG_EXOP_RES_OID ) {
00441                                    berrc = ber_scanf( &ber, "x" );
00442                             }
00443                             if ( berrc != LBER_ERROR &&
00444                                 ber_peek_tag( &ber, &len ) ==
00445                                 LDAP_TAG_EXOP_RES_VALUE ) {
00446                                    berrc = ber_scanf( &ber, "x" );
00447                             }
00448                      }
00449               }
00450 
00451               /* pull out controls (if requested and any are present) */
00452               if ( berrc != LBER_ERROR && serverctrlsp != NULL &&
00453                   ( berrc = ber_scanf( &ber, "}" )) != LBER_ERROR ) {
00454                      err = nsldapi_get_controls( &ber, serverctrlsp );
00455               }
00456        }
00457 
00458        if ( berrc == LBER_ERROR && err == LDAP_SUCCESS ) {
00459               err = LDAP_DECODING_ERROR;
00460        }
00461 
00462        if ( errcodep != NULL ) {
00463               *errcodep = errcode;
00464        }
00465        if ( matchednp != NULL ) {
00466               *matchednp = m;
00467        } else if ( m != NULL ) {
00468               NSLDAPI_FREE( m );
00469        }
00470        if ( errmsgp != NULL ) {
00471               *errmsgp = e;
00472        } else if ( e != NULL ) {
00473               NSLDAPI_FREE( e );
00474        }
00475 
00476        return( err );
00477 }