1 /* $NetBSD: slapd-common.c,v 1.2 2020/08/11 13:15:42 christos Exp $ */ 2 3 /* $OpenLDAP$ */ 4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 5 * 6 * Copyright 1999-2020 The OpenLDAP Foundation. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted only as authorized by the OpenLDAP 11 * Public License. 12 * 13 * A copy of this license is available in file LICENSE in the 14 * top-level directory of the distribution or, alternatively, at 15 * <http://www.OpenLDAP.org/license.html>. 16 */ 17 /* ACKNOWLEDGEMENTS: 18 * This work was initially developed by Howard Chu for inclusion 19 * in OpenLDAP Software. 20 */ 21 22 #include <sys/cdefs.h> 23 __RCSID("$NetBSD: slapd-common.c,v 1.2 2020/08/11 13:15:42 christos Exp $"); 24 25 #include "portable.h" 26 27 #include <stdio.h> 28 29 #include "ac/stdlib.h" 30 #include "ac/unistd.h" 31 #include "ac/string.h" 32 #include "ac/errno.h" 33 34 #include "ldap.h" 35 36 #include "ldap_pvt.h" 37 #include "slapd-common.h" 38 39 /* global vars */ 40 pid_t pid; 41 42 /* static vars */ 43 static char progname[ BUFSIZ ]; 44 tester_t progtype; 45 46 /* 47 * ignore_count[] is indexed by result code: 48 * negative for OpenLDAP client-side errors, positive for protocol codes. 49 */ 50 #define TESTER_CLIENT_FIRST LDAP_REFERRAL_LIMIT_EXCEEDED /* negative */ 51 #define TESTER_SERVER_LAST LDAP_OTHER 52 static int ignore_base [ -TESTER_CLIENT_FIRST + TESTER_SERVER_LAST + 1 ]; 53 #define ignore_count (ignore_base - TESTER_CLIENT_FIRST) 54 55 static const struct { 56 const char *name; 57 int err; 58 } ignore_str2err[] = { 59 { "OPERATIONS_ERROR", LDAP_OPERATIONS_ERROR }, 60 { "PROTOCOL_ERROR", LDAP_PROTOCOL_ERROR }, 61 { "TIMELIMIT_EXCEEDED", LDAP_TIMELIMIT_EXCEEDED }, 62 { "SIZELIMIT_EXCEEDED", LDAP_SIZELIMIT_EXCEEDED }, 63 { "COMPARE_FALSE", LDAP_COMPARE_FALSE }, 64 { "COMPARE_TRUE", LDAP_COMPARE_TRUE }, 65 { "AUTH_METHOD_NOT_SUPPORTED", LDAP_AUTH_METHOD_NOT_SUPPORTED }, 66 { "STRONG_AUTH_NOT_SUPPORTED", LDAP_STRONG_AUTH_NOT_SUPPORTED }, 67 { "STRONG_AUTH_REQUIRED", LDAP_STRONG_AUTH_REQUIRED }, 68 { "STRONGER_AUTH_REQUIRED", LDAP_STRONGER_AUTH_REQUIRED }, 69 { "PARTIAL_RESULTS", LDAP_PARTIAL_RESULTS }, 70 71 { "REFERRAL", LDAP_REFERRAL }, 72 { "ADMINLIMIT_EXCEEDED", LDAP_ADMINLIMIT_EXCEEDED }, 73 { "UNAVAILABLE_CRITICAL_EXTENSION", LDAP_UNAVAILABLE_CRITICAL_EXTENSION }, 74 { "CONFIDENTIALITY_REQUIRED", LDAP_CONFIDENTIALITY_REQUIRED }, 75 { "SASL_BIND_IN_PROGRESS", LDAP_SASL_BIND_IN_PROGRESS }, 76 77 { "NO_SUCH_ATTRIBUTE", LDAP_NO_SUCH_ATTRIBUTE }, 78 { "UNDEFINED_TYPE", LDAP_UNDEFINED_TYPE }, 79 { "INAPPROPRIATE_MATCHING", LDAP_INAPPROPRIATE_MATCHING }, 80 { "CONSTRAINT_VIOLATION", LDAP_CONSTRAINT_VIOLATION }, 81 { "TYPE_OR_VALUE_EXISTS", LDAP_TYPE_OR_VALUE_EXISTS }, 82 { "INVALID_SYNTAX", LDAP_INVALID_SYNTAX }, 83 84 { "NO_SUCH_OBJECT", LDAP_NO_SUCH_OBJECT }, 85 { "ALIAS_PROBLEM", LDAP_ALIAS_PROBLEM }, 86 { "INVALID_DN_SYNTAX", LDAP_INVALID_DN_SYNTAX }, 87 { "IS_LEAF", LDAP_IS_LEAF }, 88 { "ALIAS_DEREF_PROBLEM", LDAP_ALIAS_DEREF_PROBLEM }, 89 90 /* obsolete */ 91 { "PROXY_AUTHZ_FAILURE", LDAP_X_PROXY_AUTHZ_FAILURE }, 92 { "INAPPROPRIATE_AUTH", LDAP_INAPPROPRIATE_AUTH }, 93 { "INVALID_CREDENTIALS", LDAP_INVALID_CREDENTIALS }, 94 { "INSUFFICIENT_ACCESS", LDAP_INSUFFICIENT_ACCESS }, 95 96 { "BUSY", LDAP_BUSY }, 97 { "UNAVAILABLE", LDAP_UNAVAILABLE }, 98 { "UNWILLING_TO_PERFORM", LDAP_UNWILLING_TO_PERFORM }, 99 { "LOOP_DETECT", LDAP_LOOP_DETECT }, 100 101 { "NAMING_VIOLATION", LDAP_NAMING_VIOLATION }, 102 { "OBJECT_CLASS_VIOLATION", LDAP_OBJECT_CLASS_VIOLATION }, 103 { "NOT_ALLOWED_ON_NONLEAF", LDAP_NOT_ALLOWED_ON_NONLEAF }, 104 { "NOT_ALLOWED_ON_RDN", LDAP_NOT_ALLOWED_ON_RDN }, 105 { "ALREADY_EXISTS", LDAP_ALREADY_EXISTS }, 106 { "NO_OBJECT_CLASS_MODS", LDAP_NO_OBJECT_CLASS_MODS }, 107 { "RESULTS_TOO_LARGE", LDAP_RESULTS_TOO_LARGE }, 108 { "AFFECTS_MULTIPLE_DSAS", LDAP_AFFECTS_MULTIPLE_DSAS }, 109 110 { "OTHER", LDAP_OTHER }, 111 112 { "SERVER_DOWN", LDAP_SERVER_DOWN }, 113 { "LOCAL_ERROR", LDAP_LOCAL_ERROR }, 114 { "ENCODING_ERROR", LDAP_ENCODING_ERROR }, 115 { "DECODING_ERROR", LDAP_DECODING_ERROR }, 116 { "TIMEOUT", LDAP_TIMEOUT }, 117 { "AUTH_UNKNOWN", LDAP_AUTH_UNKNOWN }, 118 { "FILTER_ERROR", LDAP_FILTER_ERROR }, 119 { "USER_CANCELLED", LDAP_USER_CANCELLED }, 120 { "PARAM_ERROR", LDAP_PARAM_ERROR }, 121 { "NO_MEMORY", LDAP_NO_MEMORY }, 122 { "CONNECT_ERROR", LDAP_CONNECT_ERROR }, 123 { "NOT_SUPPORTED", LDAP_NOT_SUPPORTED }, 124 { "CONTROL_NOT_FOUND", LDAP_CONTROL_NOT_FOUND }, 125 { "NO_RESULTS_RETURNED", LDAP_NO_RESULTS_RETURNED }, 126 { "MORE_RESULTS_TO_RETURN", LDAP_MORE_RESULTS_TO_RETURN }, 127 { "CLIENT_LOOP", LDAP_CLIENT_LOOP }, 128 { "REFERRAL_LIMIT_EXCEEDED", LDAP_REFERRAL_LIMIT_EXCEEDED }, 129 130 { NULL } 131 }; 132 133 #define UNKNOWN_ERR (1234567890) 134 135 static int 136 tester_ignore_str2err( const char *err ) 137 { 138 int i, ignore = 1; 139 140 if ( strcmp( err, "ALL" ) == 0 ) { 141 for ( i = 0; ignore_str2err[ i ].name != NULL; i++ ) { 142 ignore_count[ ignore_str2err[ i ].err ] = 1; 143 } 144 ignore_count[ LDAP_SUCCESS ] = 0; 145 146 return 0; 147 } 148 149 if ( err[ 0 ] == '!' ) { 150 ignore = 0; 151 err++; 152 153 } else if ( err[ 0 ] == '*' ) { 154 ignore = -1; 155 err++; 156 } 157 158 for ( i = 0; ignore_str2err[ i ].name != NULL; i++ ) { 159 if ( strcmp( err, ignore_str2err[ i ].name ) == 0 ) { 160 int err = ignore_str2err[ i ].err; 161 162 if ( err != LDAP_SUCCESS ) { 163 ignore_count[ err ] = ignore; 164 } 165 166 return err; 167 } 168 } 169 170 return UNKNOWN_ERR; 171 } 172 173 int 174 tester_ignore_str2errlist( const char *err ) 175 { 176 int i; 177 char **errs = ldap_str2charray( err, "," ); 178 179 for ( i = 0; errs[ i ] != NULL; i++ ) { 180 /* TODO: allow <err>:<prog> to ignore <err> only when <prog> */ 181 (void)tester_ignore_str2err( errs[ i ] ); 182 } 183 184 ldap_charray_free( errs ); 185 186 return 0; 187 } 188 189 int 190 tester_ignore_err( int err ) 191 { 192 int rc = 1; 193 194 if ( err && TESTER_CLIENT_FIRST <= err && err <= TESTER_SERVER_LAST ) { 195 rc = ignore_count[ err ]; 196 if ( rc != 0 ) { 197 ignore_count[ err ] = rc + (rc > 0 ? 1 : -1); 198 } 199 } 200 201 /* SUCCESS is always "ignored" */ 202 return rc; 203 } 204 205 void 206 tester_init( const char *pname, tester_t ptype ) 207 { 208 pid = getpid(); 209 srand( pid ); 210 snprintf( progname, sizeof( progname ), "%s PID=%d", pname, pid ); 211 progtype = ptype; 212 } 213 214 char * 215 tester_uri( char *uri, char *host, int port ) 216 { 217 static char uribuf[ BUFSIZ ]; 218 219 if ( uri != NULL ) { 220 return uri; 221 } 222 223 snprintf( uribuf, sizeof( uribuf ), "ldap://%s:%d", host, port ); 224 225 return uribuf; 226 } 227 228 void 229 tester_ldap_error( LDAP *ld, const char *fname, const char *msg ) 230 { 231 int err; 232 char *text = NULL; 233 LDAPControl **ctrls = NULL; 234 235 ldap_get_option( ld, LDAP_OPT_RESULT_CODE, (void *)&err ); 236 if ( err != LDAP_SUCCESS ) { 237 ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void *)&text ); 238 } 239 240 fprintf( stderr, "%s: %s: %s (%d) %s %s\n", 241 progname, fname, ldap_err2string( err ), err, 242 text == NULL ? "" : text, 243 msg ? msg : "" ); 244 245 if ( text ) { 246 ldap_memfree( text ); 247 text = NULL; 248 } 249 250 ldap_get_option( ld, LDAP_OPT_MATCHED_DN, (void *)&text ); 251 if ( text != NULL ) { 252 if ( text[ 0 ] != '\0' ) { 253 fprintf( stderr, "\tmatched: %s\n", text ); 254 } 255 ldap_memfree( text ); 256 text = NULL; 257 } 258 259 ldap_get_option( ld, LDAP_OPT_SERVER_CONTROLS, (void *)&ctrls ); 260 if ( ctrls != NULL ) { 261 int i; 262 263 fprintf( stderr, "\tcontrols:\n" ); 264 for ( i = 0; ctrls[ i ] != NULL; i++ ) { 265 fprintf( stderr, "\t\t%s\n", ctrls[ i ]->ldctl_oid ); 266 } 267 ldap_controls_free( ctrls ); 268 ctrls = NULL; 269 } 270 271 if ( err == LDAP_REFERRAL ) { 272 char **refs = NULL; 273 274 ldap_get_option( ld, LDAP_OPT_REFERRAL_URLS, (void *)&refs ); 275 276 if ( refs ) { 277 int i; 278 279 fprintf( stderr, "\treferral:\n" ); 280 for ( i = 0; refs[ i ] != NULL; i++ ) { 281 fprintf( stderr, "\t\t%s\n", refs[ i ] ); 282 } 283 284 ber_memvfree( (void **)refs ); 285 } 286 } 287 } 288 289 void 290 tester_perror( const char *fname, const char *msg ) 291 { 292 int save_errno = errno; 293 char buf[ BUFSIZ ]; 294 295 fprintf( stderr, "%s: %s: (%d) %s %s\n", 296 progname, fname, save_errno, 297 AC_STRERROR_R( save_errno, buf, sizeof( buf ) ), 298 msg ? msg : "" ); 299 } 300 301 void 302 tester_error( const char *msg ) 303 { 304 fprintf( stderr, "%s: %s\n", progname, msg ); 305 } 306