1 /* 2 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 /* 7 * The contents of this file are subject to the Netscape Public 8 * License Version 1.1 (the "License"); you may not use this file 9 * except in compliance with the License. You may obtain a copy of 10 * the License at http://www.mozilla.org/NPL/ 11 * 12 * Software distributed under the License is distributed on an "AS 13 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 14 * implied. See the License for the specific language governing 15 * rights and limitations under the License. 16 * 17 * The Original Code is Mozilla Communicator client code, released 18 * March 31, 1998. 19 * 20 * The Initial Developer of the Original Code is Netscape 21 * Communications Corporation. Portions created by Netscape are 22 * Copyright (C) 1998-1999 Netscape Communications Corporation. All 23 * Rights Reserved. 24 * 25 * Contributor(s): 26 */ 27 28 /* 29 * code that is shared by two or more of the LDAP command line tools 30 */ 31 32 #include "ldaptool.h" 33 #include "fileurl.h" 34 #ifdef SOLARIS_LDAP_CMD 35 #include "solaris-int.h" 36 #include <ldap.h> 37 #include <locale.h> 38 #include <libgen.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <limits.h> 42 #endif /* SOLARIS_LDAP_CMD */ 43 44 #ifdef LDAP_TOOL_ARGPIN 45 #include "argpin.h" 46 #include "ntuserpin.h" 47 #endif /* LDAP_TOOL_ARGPIN */ 48 49 #ifndef SOLARIS_LDAP_CMD 50 #include <nspr.h> /* for PR_Cleanup() */ 51 #endif /* SOLARIS_LDAP_CMD */ 52 #include <stdlib.h> 53 #include <time.h> /* for time() and ctime() */ 54 #ifdef HAVE_SASL_OPTIONS 55 #ifdef SOLARIS_LDAP_CMD 56 #include <sasl/sasl.h> 57 #else 58 #include <sasl.h> 59 #endif /* SOLARIS_LDAP_CMD */ 60 #include "ldaptool-sasl.h" 61 #endif /* HAVE_SASL_OPTIONS */ 62 63 #ifndef SOLARIS_LDAP_CMD 64 #define gettext(s) s 65 #endif 66 67 #ifdef SOLARIS_LDAP_CMD 68 #define PATH_BUF_SIZE (PATH_MAX + 1) 69 #endif 70 71 static LDAP_REBINDPROC_CALLBACK get_rebind_credentials; 72 static void print_library_info( const LDAPAPIInfo *aip, FILE *fp ); 73 static int wait4result( LDAP *ld, int msgid, struct berval **servercredp, 74 char *msg ); 75 static int parse_result( LDAP *ld, LDAPMessage *res, 76 struct berval **servercredp, char *msg, int freeit ); 77 78 #ifdef LDAPTOOL_DEBUG_MEMORY 79 static void *ldaptool_debug_malloc( size_t size ); 80 static void *ldaptool_debug_calloc( size_t nelem, size_t elsize ); 81 static void *ldaptool_debug_realloc( void *ptr, size_t size ); 82 static void ldaptool_debug_free( void *ptr ); 83 #endif /* LDAPTOOL_DEBUG_MEMORY */ 84 85 #if defined(NET_SSL) 86 static char *certpath2keypath( char *certdbpath ); 87 static int ldaptool_setcallbacks( struct ldapssl_pkcs_fns *pfns); 88 static char * buildTokenCertName( const char *tokenName, const char *certName); 89 #ifdef FORTEZZA 90 static int ldaptool_fortezza_init( int exit_on_error ); 91 static int ldaptool_fortezza_alert( void *arg, PRBool onOpen, 92 char *string, int value1, void *value2 ); 93 static void * ldaptool_fortezza_getpin( char **passwordp ); 94 static char * ldaptool_fortezza_err2string( int err ); 95 #endif /* FORTEZZA */ 96 #endif 97 #ifdef HAVE_SASL_OPTIONS 98 static int saslSetParam(char *saslarg); 99 #endif /* HAVE_SASL_OPTIONS */ 100 101 /* 102 * display usage for common options with one exception: -f is not included 103 * since the description tends to be tool-specific. 104 * 105 * As of 1-Jul-1998, of the characters in the set [A-Za-z] the following are 106 * not currently used by any of the tools: EJgjqr 107 */ 108 void 109 ldaptool_common_usage( int two_hosts ) 110 { 111 fprintf( stderr, gettext(" -n\t\tshow what would be done but don't actually do it\n") ); 112 fprintf( stderr, gettext(" -v\t\trun in verbose mode (diagnostics to standard output)\n") ); 113 if ( two_hosts ) { 114 fprintf( stderr, gettext(" -h host\tLDAP server1 name or IP address (default: %s)\n"), LDAPTOOL_DEFHOST ); 115 fprintf( stderr, gettext(" -p port\tLDAP server1 TCP port number (default: %d)\n"), LDAP_PORT ); 116 fprintf( stderr, gettext(" -h host\tLDAP server2 name or IP address (default: %s)\n"), LDAPTOOL_DEFHOST ); 117 fprintf( stderr, gettext(" -p port\tLDAP server2 TCP port number (default: %d)\n"), LDAP_PORT ); 118 } else { 119 fprintf( stderr, gettext(" -h host\tLDAP server name or IP address (default: %s)\n"), LDAPTOOL_DEFHOST ); 120 fprintf( stderr, gettext(" -p port\tLDAP server TCP port number (default: %d)\n"), LDAP_PORT ); 121 } 122 fprintf( stderr, 123 gettext(" -V n\tLDAP protocol version number (%d or %d; default: %d)\n"), 124 LDAP_VERSION2, LDAP_VERSION3, LDAP_VERSION3 ); 125 #if defined(NET_SSL) 126 fprintf( stderr, gettext(" -Z\t\tmake an SSL-encrypted connection\n") ); 127 fprintf( stderr, gettext(" -P pathname\tpath to SSL certificate database (default: current directory)\n") ); 128 fprintf( stderr, gettext(" -N\t\tname of certificate to use for SSL client authentication\n") ); 129 #ifndef SOLARIS_LDAP_CMD 130 fprintf( stderr, gettext(" -K pathname\tpath to key database to use for SSL client authentication\n") ); 131 fprintf( stderr, gettext(" \t\t(default: path to certificate database provided with -P option)\n") ); 132 #endif /* SOLARIS_LDAP_CMD */ 133 #ifdef LDAP_TOOL_PKCS11 134 fprintf( stderr, gettext(" -m pathname\tpath to security module database\n")); 135 #endif /* LDAP_TOOL_PKCS11 */ 136 fprintf( stderr, gettext(" -W\t\tSSL key password\n") ); 137 #ifndef SOLARIS_LDAP_CMD 138 fprintf( stderr, gettext(" -3\t\tcheck hostnames in SSL certificates\n") ); 139 #endif /* SOLARIS_LDAP_CMD */ 140 141 #ifdef LDAP_TOOL_PKCS11 142 fprintf( stderr, gettext(" -Q [token][:certificate name]\tPKCS 11\n") ); 143 /* fprintf( stderr, " -X pathname\tFORTEZZA compromised key list (CKL)\n" ); */ 144 fprintf( stderr, gettext(" -I pin\tcard password file\n") ); 145 #endif /* LDAP_TOOL_PKCS11 */ 146 147 #endif /* NET_SSL */ 148 fprintf( stderr, gettext(" -D binddn\tbind dn\n") ); 149 fprintf( stderr, gettext(" -w passwd\tbind passwd (for simple authentication)\n") ); 150 fprintf( stderr, gettext(" -w - \tprompt for bind passwd (for simple authentication)\n") ); 151 fprintf( stderr, gettext(" -j file\tread bind passwd (for simple authentication)\n") ); 152 fprintf( stderr, gettext(" \t\tor SSL key password from 'file'\n") ); 153 fprintf( stderr, gettext(" -E\t\task server to expose (report) bind identity\n") ); 154 #ifdef LDAP_DEBUG 155 fprintf( stderr, gettext(" -d level\tset LDAP debugging level to `level'\n") ); 156 #endif 157 fprintf( stderr, gettext(" -R\t\tdo not automatically follow referrals\n") ); 158 fprintf( stderr, gettext(" -O limit\tmaximum number of referral hops to traverse (default: %d)\n"), LDAPTOOL_DEFREFHOPLIMIT ); 159 fprintf( stderr, gettext(" -M\t\tmanage references (treat them as regular entries)\n") ); 160 #ifndef SOLARIS_LDAP_CMD 161 fprintf( stderr, gettext(" -0\t\tignore LDAP library version mismatches\n") ); 162 #endif /* SOLARIS_LDAP_CMD */ 163 164 #ifndef NO_LIBLCACHE 165 fprintf( stderr, gettext(" -C cfgfile\tuse local database described by cfgfile\n") ); 166 #endif 167 fprintf( stderr, gettext(" -i charset\tcharacter set for command line input (default taken from locale)\n") ); 168 fprintf( stderr, gettext(" -k dir\tconversion routine directory (default: current directory)\n") ); 169 #if 0 170 /* 171 * Suppress usage for -y (old proxied authorization control) even though 172 * we still support it. We want to encourage people to use -Y instead (the 173 * new proxied authorization control). 174 */ 175 fprintf( stderr, gettext(" -y proxydn\tDN used for proxy authorization\n") ); 176 #endif 177 fprintf( stderr, gettext(" -Y proxyid\tproxied authorization id,\n") ); 178 fprintf( stderr, gettext(" \te.g, dn:uid=bjensen,dc=example,dc=com\n") ); 179 fprintf( stderr, gettext(" -H\t\tdisplay usage information\n") ); 180 #ifdef SOLARIS_LDAP_CMD 181 fprintf( stderr, gettext(" -?\t\tdisplay usage information\n") ); 182 #endif /* SOLARIS_LDAP_CMD */ 183 fprintf( stderr, gettext(" -J controloid[:criticality[:value|::b64value|:<fileurl]]\n") ); 184 fprintf( stderr, gettext("\t\tcriticality is a boolean value (default is false)\n") ); 185 #ifdef HAVE_SASL_OPTIONS 186 fprintf( stderr, gettext(" -o attrName=attrVal\tSASL options which are described in the man page\n")); 187 #endif /* HAVE_SASL_OPTIONS */ 188 } 189 190 /* globals */ 191 char *ldaptool_charset = ""; 192 char *ldaptool_host = LDAPTOOL_DEFHOST; 193 char *ldaptool_host2 = LDAPTOOL_DEFHOST; 194 int ldaptool_port = LDAP_PORT; 195 int ldaptool_port2 = LDAP_PORT; 196 int ldaptool_verbose = 0; 197 int ldaptool_not = 0; 198 #ifdef SOLARIS_LDAP_CMD 199 int ldaptool_require_binddn = 1; 200 #endif /* SOLARIS_LDAP_CMD */ 201 FILE *ldaptool_fp = NULL; 202 FILE *password_fp = NULL; 203 char *ldaptool_progname = ""; 204 char *ldaptool_nls_lang = NULL; 205 char *proxyauth_id = NULL; 206 int proxyauth_version = 2; /* use newer proxy control */ 207 LDAPControl *ldaptool_request_ctrls[CONTROL_REQUESTS] = {0}; 208 #ifdef LDAP_DEBUG 209 int ldaptool_dbg_lvl = 0; 210 #endif /* LDAP_DEBUG */ 211 212 /* statics */ 213 static char *binddn = NULL; 214 static char *passwd = NULL; 215 static int send_auth_response_ctrl = 0; 216 static int user_specified_port = 0; 217 static int user_specified_port2 = 0; 218 static int chase_referrals = 1; 219 static int lib_version_mismatch_is_fatal = 1; 220 static int ldversion = -1; /* use default */ 221 static int refhoplim = LDAPTOOL_DEFREFHOPLIMIT; 222 static int send_manage_dsait_ctrl = 0; 223 static int prompt_password = 0; 224 #ifdef HAVE_SASL_OPTIONS 225 static unsigned sasl_flags = LDAP_SASL_INTERACTIVE; 226 static char *sasl_mech = NULL; 227 static char *sasl_authid = NULL; 228 static char *sasl_mode = NULL; 229 static char *sasl_realm = NULL; 230 static char *sasl_username = NULL; 231 static char *sasl_secprops = NULL; 232 static int ldapauth = -1; 233 #endif /* HAVE_SASL_OPTIONS */ 234 235 #ifndef NO_LIBLCACHE 236 static char *cache_config_file = NULL; 237 #endif /* !NO_LIBLCACHE */ 238 #if defined(NET_SSL) 239 static int secure = 0; 240 static int isZ = 0; 241 static int isN = 0; 242 static int isW = 0; 243 static int isw = 0; 244 static int isD = 0; 245 static int isj = 0; 246 static int ssl_strength = LDAPTOOL_DEFSSLSTRENGTH; 247 #ifdef SOLARIS_LDAP_CMD 248 static char pathname[PATH_BUF_SIZE]; 249 #endif 250 static char *ssl_certdbpath = NULL; 251 static char *ssl_keydbpath = NULL; 252 static char *ssl_keyname = NULL; 253 static char *ssl_certname = NULL; 254 static char *ssl_passwd = NULL; 255 256 #ifdef LDAP_TOOL_PKCS11 257 static char *ssl_secmodpath = NULL; 258 259 static char *pkcs_token = NULL; 260 261 static char *ssl_donglefile = NULL; 262 263 #if 0 264 static char *pkcs_pin = NULL; 265 #endif 266 static struct ldapssl_pkcs_fns local_pkcs_fns = 267 {0,NULL,NULL,NULL,NULL,NULL,NULL,NULL, NULL }; 268 269 #ifdef FORTEZZA 270 static uint32 fortezza_cardmask = 0; 271 static char *fortezza_personality = NULL; 272 static char *fortezza_krlfile = NULL; 273 static char *fortezza_pin = NULL; 274 #endif /* FORTEZZA */ 275 #endif /* LDAP_TOOL_PKCS11 */ 276 #endif /* NET_SSL */ 277 278 /* 279 * Handle general initialization and options that are common to all of 280 * the LDAP tools. 281 * Handle options that are common to all of the LDAP tools. 282 * Note the the H option is included here but handled via the 283 * extra_opt_callback function (along with any "extra_opts" ). 284 * 285 * Return: final value for optind or -1 if usage should be displayed (for 286 * some fatal errors, we call exit here). 287 */ 288 int 289 ldaptool_process_args( int argc, char **argv, char *extra_opts, 290 int two_hosts, void (*extra_opt_callback)( int option, char *optarg )) 291 { 292 int rc, i, hostnum; 293 char *optstring, *common_opts; 294 extern char *optarg; 295 extern int optind; 296 LDAPAPIInfo ldai; 297 char *ctrl_arg, *ctrl_oid=NULL, *ctrl_value=NULL; 298 int ctrl_criticality=0, vlen; 299 LDAPControl *ldctrl; 300 #ifdef SOLARIS_LDAP_CMD 301 struct stat st; 302 #endif 303 304 305 /* 306 * Set program name global based on argv[0]. 307 */ 308 if (( ldaptool_progname = strrchr( argv[ 0 ], '/' )) == NULL ) { 309 ldaptool_progname = argv[ 0 ]; 310 } else { 311 ++ldaptool_progname; 312 } 313 314 #ifdef LDAPTOOL_DEBUG_MEMORY 315 { 316 struct ldap_memalloc_fns mafns = { 317 ldaptool_debug_malloc, 318 ldaptool_debug_calloc, 319 ldaptool_debug_realloc, 320 ldaptool_debug_free 321 }; 322 323 ldap_set_option( NULL, LDAP_OPT_MEMALLOC_FN_PTRS, &mafns ); 324 } 325 #endif /* LDAPTOOL_DEBUG_MEMORY */ 326 327 #ifdef LDAP_DEBUG 328 i = LDAP_DEBUG_ANY; 329 ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, (void *) &i); 330 #endif 331 332 /* 333 * Perform a sanity check on the revision of the LDAP API library to 334 * make sure it is at least as new as the one we were compiled against. 335 * If the API implementation is from the same vendor as we were compiled 336 * against, we also check to make sure the vendor version is at least 337 * as new as the library we were compiled against. 338 * 339 * Version differences are fatal unless the -0 option is passed on the 340 * tool command line (that's a zero, not an oh). We check for the 341 * presence of -0 in a crude way to it must appear by itself in argv. 342 */ 343 for ( i = 1; i < argc; ++i ) { 344 if ( strcmp( argv[i], "-0" ) == 0 ) { 345 lib_version_mismatch_is_fatal = 0; 346 break; 347 } 348 } 349 350 memset( &ldai, 0, sizeof(ldai)); 351 ldai.ldapai_info_version = LDAP_API_INFO_VERSION; 352 if (( rc = ldap_get_option( NULL, LDAP_OPT_API_INFO, &ldai )) != 0 ) { 353 fprintf( stderr, gettext("%s: unable to retrieve LDAP library version" 354 " information;\n\tthis program requires an LDAP library that" 355 " implements revision\n\t%d or greater of the LDAP API.\n"), 356 ldaptool_progname, LDAP_API_VERSION ); 357 if ( lib_version_mismatch_is_fatal ) { 358 exit( LDAP_LOCAL_ERROR ); 359 } 360 } else if ( ldai.ldapai_api_version < LDAP_API_VERSION ) { 361 fprintf( stderr, gettext("%s: this program requires an LDAP library that" 362 " implements revision\n\t%d or greater of the LDAP API;" 363 " running with revision %d.\n"), 364 ldaptool_progname, LDAP_API_VERSION, ldai.ldapai_api_version ); 365 if ( lib_version_mismatch_is_fatal ) { 366 exit( LDAP_LOCAL_ERROR ); 367 } 368 } else if ( strcmp( ldai.ldapai_vendor_name, LDAP_VENDOR_NAME ) != 0) { 369 fprintf( stderr, gettext("%s: this program requires %s's LDAP\n" 370 "\tlibrary version %2.2f or greater; running with\n" 371 "\t%s's version %2.2f.\n"), 372 ldaptool_progname, LDAP_VENDOR_NAME, 373 (float)LDAP_VENDOR_VERSION / 100, 374 ldai.ldapai_vendor_name, 375 (float)ldai.ldapai_vendor_version / 100 ); 376 if ( lib_version_mismatch_is_fatal ) { 377 exit( LDAP_LOCAL_ERROR ); 378 } 379 } else if (ldai.ldapai_vendor_version < LDAP_VENDOR_VERSION ) { 380 fprintf( stderr, gettext("%s: this program requires %s's LDAP\n" 381 "\tlibrary version %2.2f or greater; running with" 382 " version %2.2f.\n"), 383 ldaptool_progname, LDAP_VENDOR_NAME, 384 (float)LDAP_VENDOR_VERSION / 100, 385 (float)ldai.ldapai_vendor_version / 100 ); 386 if ( lib_version_mismatch_is_fatal ) { 387 exit( LDAP_LOCAL_ERROR ); 388 } 389 } 390 391 /* 392 * Process command line options. 393 */ 394 if ( extra_opts == NULL ) { 395 extra_opts = ""; 396 } 397 398 #ifdef HAVE_SASL_OPTIONS 399 #ifdef SOLARIS_LDAP_CMD 400 common_opts = "nvEMRH?Zd:D:f:h:j:N:O:o:P:p:W:w:V:i:k:y:Y:J:"; 401 #else 402 common_opts = "nvEMRHZ03d:D:f:h:j:I:K:N:O:o:P:p:Q:W:w:V:X:m:i:k:y:Y:J:"; 403 #endif /* SOLARIS_LDAP_CMD */ 404 #else 405 common_opts = "nvEMRHZ03d:D:f:h:j:I:K:N:O:P:p:Q:W:w:V:X:m:i:k:y:Y:J:"; 406 #endif /* HAVE_SASL_OPTIONS */ 407 408 /* note: optstring must include room for liblcache "C:" option */ 409 if (( optstring = (char *) malloc( strlen( extra_opts ) + strlen( common_opts ) 410 + 3 )) == NULL ) { 411 perror( "malloc" ); 412 exit( LDAP_NO_MEMORY ); 413 } 414 415 #ifdef NO_LIBLCACHE 416 sprintf( optstring, "%s%s", common_opts, extra_opts ); 417 #else 418 sprintf( optstring, "%s%sC:", common_opts, extra_opts ); 419 #endif 420 421 hostnum = 0; 422 while ( (i = getopt( argc, argv, optstring )) != EOF ) { 423 switch( i ) { 424 case 'n': /* do Not do any LDAP operations */ 425 ++ldaptool_not; 426 break; 427 case 'v': /* verbose mode */ 428 ++ldaptool_verbose; 429 break; 430 case 'd': 431 #ifdef LDAP_DEBUG 432 ldaptool_dbg_lvl = atoi( optarg ); /* */ 433 #ifdef SOLARIS_LDAP_CMD 434 ldap_set_option(NULL, LBER_OPT_DEBUG_LEVEL, 435 (void *)&ldaptool_dbg_lvl); 436 #else 437 ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL, 438 (void *)&ldaptool_dbg_lvl); 439 #endif /* SOLARIS_LDAP_CMD */ 440 ldaptool_dbg_lvl |= LDAP_DEBUG_ANY; 441 ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, 442 (void *)&ldaptool_dbg_lvl); 443 #else /* LDAP_DEBUG */ 444 fprintf( stderr, gettext("compile with -DLDAP_DEBUG for debugging\n") ); 445 #endif /* LDAP_DEBUG */ 446 break; 447 case 'R': /* don't automatically chase referrals */ 448 chase_referrals = 0; 449 break; 450 #ifndef NO_LIBLCACHE 451 case 'C': /* search local database */ 452 cache_config_file = strdup( optarg ); 453 break; 454 #endif 455 case 'f': /* input file */ 456 if ( optarg[0] == '-' && optarg[1] == '\0' ) { 457 ldaptool_fp = stdin; 458 } else if (( ldaptool_fp = ldaptool_open_file( optarg, "r" )) == NULL ) { 459 perror( optarg ); 460 exit( LDAP_PARAM_ERROR ); 461 } 462 break; 463 case 'h': /* ldap host */ 464 if ( hostnum == 0 ) { 465 ldaptool_host = strdup( optarg ); 466 } else { 467 ldaptool_host2 = strdup( optarg ); 468 } 469 ++hostnum; 470 break; 471 case 'D': /* bind DN */ 472 isD = 1; 473 binddn = strdup( optarg ); 474 break; 475 case 'E': /* expose bind identity via auth. response control */ 476 ++send_auth_response_ctrl; 477 break; 478 479 case 'p': /* ldap port */ 480 if ( !user_specified_port ) { 481 ++user_specified_port; 482 ldaptool_port = atoi( optarg ); 483 } else { 484 ++user_specified_port2; 485 ldaptool_port2 = atoi( optarg ); 486 } 487 break; 488 #if defined(NET_SSL) 489 case 'P': /* path to security database */ 490 secure = 1; /* do SSL encryption */ 491 #ifndef SOLARIS_LDAP_CMD 492 ssl_certdbpath = strdup(optarg); 493 if (NULL == ssl_certdbpath) { 494 perror("malloc"); 495 exit( LDAP_NO_MEMORY ); 496 } 497 #else 498 /* 499 * Verify whether it's a base directory or a cert db file. 500 * If it is not a directory, truncate the file name as 501 * the revised NSS_Init() doesn't take file name any longer. 502 */ 503 if (strlcpy(pathname, optarg, PATH_BUF_SIZE) >= PATH_BUF_SIZE) { 504 fprintf(stderr, gettext("\"-P\": Path name is too " 505 "long\n")); 506 exit(LDAP_PARAM_ERROR); 507 } 508 509 if (stat(pathname, &st) != 0) { 510 perror("stat"); 511 fprintf(stderr, gettext("\"-P\": Path name is " 512 "invalid\n")); 513 exit(LDAP_PARAM_ERROR); 514 } else { 515 if (S_ISREG(st.st_mode)) { 516 /* redir to a regular file's dir name */ 517 ssl_certdbpath = dirname(pathname); 518 } else 519 ssl_certdbpath = pathname; 520 } 521 #endif /* SOLARIS_LDAP_CMD */ 522 break; 523 case 'Z': /* do SSL encryption */ 524 secure = 1; 525 isZ = 1; 526 break; 527 case 'N': /* nickname of cert. to use for client auth. */ 528 ssl_certname = strdup( optarg ); 529 if (NULL == ssl_certname) 530 { 531 perror("malloc"); 532 exit( LDAP_NO_MEMORY ); 533 } 534 isN = 1; 535 break; 536 #ifndef SOLARIS_LDAP_CMD 537 case 'K': /* location of key database */ 538 ssl_keydbpath = strdup( optarg ); 539 if (NULL == ssl_keydbpath) 540 { 541 perror("malloc"); 542 exit( LDAP_NO_MEMORY ); 543 } 544 break; 545 #endif /* SOLARIS_LDAP_CMD */ 546 547 case 'W': /* SSL key password */ 548 ssl_passwd = strdup( optarg ); 549 if (NULL == ssl_passwd) 550 { 551 perror("malloc"); 552 exit( LDAP_NO_MEMORY ); 553 } 554 isW = 1; 555 break; 556 557 #ifndef SOLARIS_LDAP_CMD 558 case '3': /* check hostnames in SSL certificates ("no third") */ 559 ssl_strength = LDAPSSL_AUTH_CNCHECK; 560 break; 561 #endif /* SOLARIS_LDAP_CMD */ 562 563 #ifdef LDAP_TOOL_PKCS11 564 case 'm': /* SSL secmod path */ 565 ssl_secmodpath = strdup( optarg); 566 if (NULL == ssl_secmodpath) 567 { 568 perror("malloc"); 569 exit( LDAP_NO_MEMORY ); 570 } 571 break; 572 573 case 'Q': /* FORTEZZA [card][:personality] */ 574 pkcs_token = strdup(optarg); 575 if (NULL == pkcs_token) 576 { 577 perror("malloc"); 578 exit( LDAP_NO_MEMORY ); 579 } 580 581 break; 582 /* This option removed to prevent interference 583 with the getEffectiveRights option, also -X 584 case 'X': * path to FORTEZZA CKL file * 585 586 fortezza_krlfile = strdup( optarg ); 587 588 589 break; 590 */ 591 case 'I': /* FORTEZZA PIN (password file) */ 592 ssl_donglefile = strdup( optarg ); 593 594 break; 595 #endif /* LDAP_TOOL_PKCS11 */ 596 597 #endif /* NET_SSL */ 598 case 'w': /* bind password */ 599 isw = 1; 600 if ( optarg[0] == '-' && optarg[1] == '\0' ) 601 prompt_password = 1; 602 else 603 passwd = strdup( optarg ); 604 break; 605 case 'j': /* bind password or SSL key password from file */ 606 isj = 1; 607 if ((password_fp = fopen( optarg, "r" )) == NULL ) { 608 fprintf(stderr, gettext("%s: Unable to open '%s' file\n"), 609 ldaptool_progname, optarg); 610 exit( LDAP_PARAM_ERROR ); 611 } 612 break; 613 case 'O': /* referral hop limit */ 614 refhoplim = atoi( optarg ); 615 break; 616 case 'V': /* protocol version */ 617 ldversion = atoi (optarg); 618 if ( ldversion != LDAP_VERSION2 && ldversion != LDAP_VERSION3 ) { 619 fprintf( stderr, gettext("%s: LDAP protocol version %d is not " 620 "supported (use -V%d or -V%d)\n"), 621 ldaptool_progname, ldversion, LDAP_VERSION2, 622 LDAP_VERSION3 ); 623 exit( LDAP_PARAM_ERROR ); 624 } 625 break; 626 case 'M': /* send a manageDsaIT control */ 627 send_manage_dsait_ctrl = 1; 628 break; 629 630 case 'i': /* character set specified */ 631 ldaptool_charset = strdup( optarg ); 632 if (NULL == ldaptool_charset) 633 { 634 perror( "malloc" ); 635 exit( LDAP_NO_MEMORY ); 636 } 637 638 break; 639 case 'k': /* conversion directory */ 640 ldaptool_convdir = strdup( optarg ); 641 if (NULL == ldaptool_convdir) 642 { 643 perror( "malloc" ); 644 exit( LDAP_NO_MEMORY ); 645 } 646 break; 647 case 'y': /* old (version 1) proxied authorization control */ 648 proxyauth_version = 1; 649 case 'Y': /* new (version 2 ) proxied authorization control */ 650 /*FALLTHRU*/ 651 proxyauth_id = strdup(optarg); 652 if (NULL == proxyauth_id) 653 { 654 perror( "malloc" ); 655 exit( LDAP_NO_MEMORY ); 656 } 657 658 break; 659 660 #ifndef SOLARIS_LDAP_CMD 661 case '0': /* zero -- override LDAP library version check */ 662 break; /* already handled above */ 663 #endif /* SOLARIS_LDAP_CMD */ 664 case 'J': /* send an arbitrary control */ 665 if ( (ctrl_arg = strdup( optarg)) == NULL ) { 666 perror ("strdup"); 667 exit (LDAP_NO_MEMORY); 668 } 669 if (ldaptool_parse_ctrl_arg(ctrl_arg, ':', &ctrl_oid, 670 &ctrl_criticality, &ctrl_value, &vlen)) { 671 return (-1); 672 } 673 ldctrl = calloc(1,sizeof(LDAPControl)); 674 if (ctrl_value) { 675 rc = ldaptool_berval_from_ldif_value( ctrl_value, 676 vlen, &(ldctrl->ldctl_value), 677 1 /* recognize file URLs */, 678 0 /* always try file */, 679 1 /* report errors */ ); 680 if ((rc = ldaptool_fileurlerr2ldaperr( rc )) != LDAP_SUCCESS) { 681 fprintf( stderr, gettext("Unable to parse %s\n"), ctrl_value); 682 return (-1); 683 } 684 } 685 ldctrl->ldctl_oid = ctrl_oid; 686 ldctrl->ldctl_iscritical = ctrl_criticality; 687 ldaptool_add_control_to_array(ldctrl, ldaptool_request_ctrls); 688 break; 689 #ifdef HAVE_SASL_OPTIONS 690 case 'o': /* attribute assignment */ 691 if ((rc = saslSetParam(optarg)) == -1) { 692 return (-1); 693 } 694 ldapauth = LDAP_AUTH_SASL; 695 ldversion = LDAP_VERSION3; 696 break; 697 #endif /* HAVE_SASL_OPTIONS */ 698 default: 699 (*extra_opt_callback)( i, optarg ); 700 } 701 } 702 703 704 /* If '-Z' is specified, check if '-P' is specified too. */ 705 if ( isN || isW ) { 706 if ( !isZ ) { 707 fprintf( stderr, gettext("%s: with -N, -W options, please specify -Z\n\n"), ldaptool_progname ); 708 return (-1); 709 } 710 } 711 712 /* if '-N' is specified, -W is needed too */ 713 if ( isN && NULL == ssl_passwd ) { 714 fprintf( stderr, gettext("%s: with the -N option, please specify -W also\n\n"), 715 ldaptool_progname ); 716 return (-1); 717 } 718 719 #ifdef SOLARIS_LDAP_CMD 720 if ( isj && ( isw || isW )) { 721 fprintf(stderr, gettext("%s: -j and -w or -W options cannot be specified simultaneously\n\n"), ldaptool_progname ); 722 #else 723 if ( isj && isw ) { 724 fprintf(stderr, gettext("%s: -j and -w options cannot be specified simultaneously\n\n"), ldaptool_progname ); 725 #endif /* SOLARIS_LDAP_CMD */ 726 return (-1); 727 } 728 729 /* complain if -j or -w does not also have -D, unless using SASL */ 730 #ifdef HAVE_SASL_OPTIONS 731 if ( (isj || isw) && !isD && ( ldapauth != LDAP_AUTH_SASL ) ) { 732 #else 733 if ( (isj || isw) && !isD ) { 734 #endif 735 fprintf(stderr, gettext("%s: with -j, -w options, please specify -D\n\n"), ldaptool_progname ); 736 return (-1); 737 } 738 739 /* use default key and cert DB paths if not set on the command line */ 740 if ( NULL == ssl_keydbpath ) { 741 if ( NULL == ssl_certdbpath ) { 742 ssl_keydbpath = LDAPTOOL_DEFKEYDBPATH; 743 } else { 744 ssl_keydbpath = certpath2keypath( ssl_certdbpath ); 745 } 746 } 747 if ( NULL == ssl_certdbpath ) { 748 ssl_certdbpath = LDAPTOOL_DEFCERTDBPATH; 749 } 750 751 if (prompt_password != 0) { 752 char *password_string = "Enter bind password: "; 753 754 #if defined(_WIN32) 755 char pbuf[257]; 756 fputs(password_string,stdout); 757 fflush(stdout); 758 if (fgets(pbuf,256,stdin) == NULL) { 759 passwd = NULL; 760 } else { 761 char *tmp; 762 763 tmp = strchr(pbuf,'\n'); 764 if (tmp) *tmp = '\0'; 765 tmp = strchr(pbuf,'\r'); 766 if (tmp) *tmp = '\0'; 767 passwd = strdup(pbuf); 768 } 769 #else 770 #if defined(SOLARIS) 771 /* 256 characters on Solaris */ 772 passwd = getpassphrase(password_string); 773 #else 774 /* limited to 16 chars on Tru64, 32 on AIX */ 775 passwd = getpass(password_string); 776 #endif 777 #endif 778 779 } else if (password_fp != NULL) { 780 char *linep = NULL; 781 int increment = 0; 782 int c, index; 783 784 /* allocate initial block of memory */ 785 if ((linep = (char *)malloc(BUFSIZ)) == NULL) { 786 fprintf( stderr, gettext("%s: not enough memory to read password from file\n"), ldaptool_progname ); 787 exit( LDAP_NO_MEMORY ); 788 } 789 increment++; 790 index = 0; 791 while ((c = fgetc( password_fp )) != '\n' && c != EOF) { 792 793 /* check if we will overflow the buffer */ 794 if ((c != EOF) && (index == ((increment * BUFSIZ) -1))) { 795 796 /* if we did, add another BUFSIZ worth of bytes */ 797 if ((linep = (char *) 798 realloc(linep, (increment + 1) * BUFSIZ)) == NULL) { 799 fprintf( stderr, gettext("%s: not enough memory to read password from file\n"), ldaptool_progname ); 800 exit( LDAP_NO_MEMORY ); 801 } 802 increment++; 803 } 804 linep[index++] = c; 805 } 806 linep[index] = '\0'; 807 passwd = linep; 808 } 809 810 #ifdef SOLARIS_LDAP_CMD 811 if (binddn != NULL && passwd == NULL) { 812 char *password_string = gettext("Enter bind password: "); 813 passwd = getpassphrase(password_string); 814 } 815 816 #ifdef HAVE_SASL_OPTIONS 817 if (ldapauth == LDAP_AUTH_SASL) { 818 /* BindDN not required for SASL */ 819 ldaptool_require_binddn = 0; 820 } 821 #endif /* HAVE_SASL_OPTIONS */ 822 823 #ifdef NET_SSL 824 if (secure == 1) { 825 /* BindDN not required for SSL */ 826 ldaptool_require_binddn = 0; 827 } 828 #endif /* NET_SSL */ 829 830 if (ldaptool_require_binddn && binddn == NULL && passwd == NULL) { 831 fprintf(stderr, 832 gettext("%s: DN and Bind Password are required.\n"), 833 ldaptool_progname ); 834 exit(1); 835 } 836 #endif /* SOLARIS_LDAP_CMD */ 837 838 /* 839 * If verbose (-v) flag was passed in, display program name and start time. 840 * If the verbose flag was passed at least twice (-vv), also display 841 * information about the API library we are running with. 842 */ 843 if ( ldaptool_verbose ) { 844 time_t curtime; 845 846 curtime = time( NULL ); 847 printf( gettext("%s: started %s\n"), ldaptool_progname, ctime( &curtime )); 848 if ( ldaptool_verbose > 1 ) { 849 print_library_info( &ldai, stdout ); 850 } 851 } 852 853 #ifdef LDAP_TOOL_PKCS11 854 if ((NULL != pkcs_token) && (NULL != ssl_certname)) { 855 char *result; 856 857 if ( (result = buildTokenCertName( pkcs_token, ssl_certname)) != NULL){ 858 free( ssl_certname ); 859 ssl_certname = result; 860 } 861 } 862 #endif /* LDAP_TOOL_PKCS11 */ 863 864 free( optstring ); 865 866 /* 867 * Clean up and return index of first non-option argument. 868 */ 869 if ( ldai.ldapai_extensions != NULL ) { 870 ldap_value_free( ldai.ldapai_extensions ); 871 } 872 if ( ldai.ldapai_vendor_name != NULL ) { 873 ldap_memfree( ldai.ldapai_vendor_name ); 874 } 875 876 #ifdef HAVE_SASL_OPTIONS 877 if (ldversion == LDAP_VERSION2 && ldapauth == LDAP_AUTH_SASL) { 878 fprintf( stderr, gettext("Incompatible with version %d\n"), ldversion); 879 return (-1); 880 } 881 #endif /* HAVE_SASL_OPTIONS */ 882 return( optind ); 883 } 884 885 886 /* 887 * Write detailed information about the API library we are running with to fp. 888 */ 889 static void 890 print_library_info( const LDAPAPIInfo *aip, FILE *fp ) 891 { 892 int i; 893 LDAPAPIFeatureInfo fi; 894 895 fprintf( fp, gettext("LDAP Library Information -\n" 896 " Highest supported protocol version: %d\n" 897 " LDAP API revision: %d\n" 898 " API vendor name: %s\n" 899 " Vendor-specific version: %.2f\n"), 900 aip->ldapai_protocol_version, aip->ldapai_api_version, 901 aip->ldapai_vendor_name, 902 (float)aip->ldapai_vendor_version / 100.0 ); 903 904 if ( aip->ldapai_extensions != NULL ) { 905 fputs( gettext(" LDAP API Extensions:\n"), fp ); 906 907 for ( i = 0; aip->ldapai_extensions[i] != NULL; i++ ) { 908 fprintf( fp, gettext(" %s"), aip->ldapai_extensions[i] ); 909 fi.ldapaif_info_version = LDAP_FEATURE_INFO_VERSION; 910 fi.ldapaif_name = aip->ldapai_extensions[i]; 911 fi.ldapaif_version = 0; 912 913 if ( ldap_get_option( NULL, LDAP_OPT_API_FEATURE_INFO, &fi ) 914 != 0 ) { 915 fprintf( fp, gettext(" %s: ldap_get_option( NULL," 916 " LDAP_OPT_API_FEATURE_INFO, ... ) for %s failed" 917 " (Feature Info version: %d)\n"), ldaptool_progname, 918 fi.ldapaif_name, fi.ldapaif_info_version ); 919 } else { 920 fprintf( fp, gettext(" (revision %d)\n"), fi.ldapaif_version); 921 } 922 } 923 } 924 fputc( '\n', fp ); 925 } 926 927 928 929 #ifdef LDAP_TOOL_ARGPIN 930 static int PinArgRegistration( void ) 931 { 932 933 /* pkcs_init was successful register the pin args */ 934 935 SVRCOREArgPinObj *ArgPinObj; 936 char *tokenName; 937 #ifndef _WIN32 938 SVRCOREStdPinObj *StdPinObj; 939 #else 940 SVRCOREFilePinObj *FilePinObj; 941 SVRCOREAltPinObj *AltPinObj; 942 SVRCORENTUserPinObj *NTUserPinObj; 943 int err; 944 #endif 945 char *pin; 946 char *filename; 947 /* Create and register the pin object for PKCS 11 */ 948 local_pkcs_fns.pkcs_getdonglefilename(NULL, &filename); 949 local_pkcs_fns.pkcs_getpin(NULL, "", &pin); 950 #ifndef _WIN32 951 if ( SVRCORE_CreateStdPinObj(&StdPinObj, filename, PR_TRUE) != 952 SVRCORE_Success) { 953 fprintf(stderr, gettext("Security Initialization: Unable to create PinObj " 954 "(%d)"), PR_GetError()); 955 return -1; 956 } 957 if (pin != NULL) 958 { 959 local_pkcs_fns.pkcs_gettokenname(NULL, &tokenName); 960 SVRCORE_CreateArgPinObj(&ArgPinObj, tokenName, pin, (SVRCOREPinObj *)StdPinObj); 961 SVRCORE_RegisterPinObj((SVRCOREPinObj *)ArgPinObj); 962 } 963 else 964 { 965 SVRCORE_RegisterPinObj((SVRCOREPinObj *)StdPinObj); 966 } 967 #else 968 if (NULL != pin) 969 { 970 local_pkcs_fns.pkcs_gettokenname(NULL, &tokenName); 971 if ((err = SVRCORE_CreateNTUserPinObj(&NTUserPinObj)) != SVRCORE_Success){ 972 fprintf(stderr, gettext("Security Initialization: Unable to create NTUserPinObj " 973 "(%d)"), PR_GetError()); 974 exit( LDAP_LOCAL_ERROR ); 975 } 976 if ((err = SVRCORE_CreateArgPinObj(&ArgPinObj, tokenName, pin, 977 (SVRCOREPinObj *)NTUserPinObj)) != SVRCORE_Success) 978 { 979 fprintf(stderr, gettext("Security Initialization: Unable to create ArgPinObj " 980 "(%d)"), PR_GetError()); 981 return -1; 982 983 } 984 SVRCORE_RegisterPinObj((SVRCOREPinObj *)ArgPinObj); 985 986 } 987 else 988 { 989 if ((err = SVRCORE_CreateNTUserPinObj(&NTUserPinObj)) != SVRCORE_Success){ 990 fprintf(stderr, gettext("Security Initialization: Unable to create NTUserPinObj " 991 "(%d)"), PR_GetError()); 992 return -1; 993 } 994 if (filename && *filename) 995 { 996 if ((err = SVRCORE_CreateFilePinObj(&FilePinObj, filename)) != 997 SVRCORE_Success) { 998 fprintf(stderr, gettext("Security Initialization: Unable to create FilePinObj " 999 "(%d)"), PR_GetError()); 1000 return -1; 1001 1002 } 1003 if ((err = SVRCORE_CreateAltPinObj(&AltPinObj, (SVRCOREPinObj *)FilePinObj, 1004 (SVRCOREPinObj *)NTUserPinObj)) != SVRCORE_Success) { 1005 fprintf(stderr, gettext("Security Initialization: Unable to create AltPinObj " 1006 "(%d)"), PR_GetError()); 1007 return -1; 1008 } 1009 SVRCORE_RegisterPinObj((SVRCOREPinObj *)AltPinObj); 1010 } 1011 else 1012 { 1013 SVRCORE_RegisterPinObj((SVRCOREPinObj *)NTUserPinObj); 1014 } 1015 } 1016 #endif 1017 return LDAP_SUCCESS; 1018 1019 } 1020 #endif /* LDAP_TOOL_ARGPIN */ 1021 1022 1023 /* 1024 * initialize and return an LDAP session handle. 1025 * if errors occur, we exit here. 1026 */ 1027 LDAP * 1028 ldaptool_ldap_init( int second_host ) 1029 { 1030 LDAP *ld = NULL; 1031 char *host; 1032 int port, rc, user_port; 1033 1034 if ( ldaptool_not ) { 1035 return( NULL ); 1036 } 1037 1038 if ( second_host ) { 1039 host = ldaptool_host2; 1040 port = ldaptool_port2; 1041 user_port = user_specified_port2; 1042 } else { 1043 host = ldaptool_host; 1044 port = ldaptool_port; 1045 user_port = user_specified_port; 1046 } 1047 1048 1049 if ( ldaptool_verbose ) { 1050 printf( gettext("ldap_init( %s, %d )\n"), host, port ); 1051 } 1052 1053 #if defined(NET_SSL) 1054 /* 1055 * Initialize security libraries and databases and LDAP session. If 1056 * ssl_certname is not NULL, then we will attempt to use client auth. 1057 * if the server supports it. 1058 */ 1059 #ifdef LDAP_TOOL_PKCS11 1060 ldaptool_setcallbacks( &local_pkcs_fns ); 1061 1062 if ( !second_host && secure 1063 &&(rc = ldapssl_pkcs_init( &local_pkcs_fns)) < 0) { 1064 /* secure connection requested -- fail if no SSL */ 1065 #ifndef SOLARIS_LDAP_CMD 1066 rc = PORT_GetError(); 1067 #endif /* SOLARIS_LDAP_CMD */ 1068 fprintf( stderr, gettext("SSL initialization failed: error %d (%s)\n"), 1069 rc, ldapssl_err2string( rc )); 1070 exit( LDAP_LOCAL_ERROR ); 1071 } 1072 1073 #ifdef LDAP_TOOL_ARGPIN 1074 if (secure) { 1075 if (PinArgRegistration( )) { 1076 exit( LDAP_LOCAL_ERROR); 1077 } 1078 } 1079 #endif /* LDAP_TOOL_ARGPIN */ 1080 1081 #else /* LDAP_TOOL_PKCS11 */ 1082 if ( !second_host && secure 1083 &&(rc = ldapssl_client_init( ssl_certdbpath, NULL )) < 0) { 1084 /* secure connection requested -- fail if no SSL */ 1085 #ifndef SOLARIS_LDAP_CMD 1086 rc = PORT_GetError(); 1087 #endif /* SOLARIS_LDAP_CMD */ 1088 fprintf( stderr, gettext("SSL initialization failed: error %d (%s)\n"), 1089 rc, ldapssl_err2string( rc )); 1090 exit( LDAP_LOCAL_ERROR ); 1091 } 1092 #endif /* LDAP_TOOL_PKCS11 */ 1093 1094 /* set the default SSL strength (used for all future ld's we create) */ 1095 if ( ldapssl_set_strength( NULL, ssl_strength ) < 0 ) { 1096 perror( "ldapssl_set_strength" ); 1097 exit( LDAP_LOCAL_ERROR ); 1098 } 1099 1100 1101 if (secure) { 1102 if ( !user_port ) { 1103 port = LDAPS_PORT; 1104 } 1105 1106 if (( ld = ldapssl_init( host, port, 1107 secure )) != NULL && ssl_certname != NULL ) 1108 if (ldapssl_enable_clientauth( ld, ssl_keydbpath, ssl_passwd, 1109 ssl_certname ) != 0 ) { 1110 exit ( ldaptool_print_lderror( ld, "ldapssl_enable_clientauth", 1111 LDAPTOOL_CHECK4SSL_ALWAYS )); 1112 } 1113 } else { 1114 /* In order to support IPv6, we use NSPR I/O */ 1115 #ifdef SOLARIS_LDAP_CMD 1116 ld = ldap_init( host, port ); 1117 #else 1118 ld = prldap_init( host, port, 0 /* not shared across threads */ ); 1119 #endif /* SOLARIS_LDAP_CMD */ 1120 } 1121 1122 #else /* NET_SSL */ 1123 /* In order to support IPv6, we use NSPR I/O */ 1124 #ifdef SOLARIS_LDAP_CMD 1125 ld = ldap_init( host, port ); 1126 #else 1127 ld = prldap_init( host, port, 0 /* not shared across threads */ ); 1128 #endif /* SOLARIS_LDAP_CMD */ 1129 #endif /* NET_SSL */ 1130 1131 if ( ld == NULL ) { 1132 perror( "ldap_init" ); 1133 exit( LDAP_LOCAL_ERROR ); 1134 } 1135 1136 #ifndef NO_LIBLCACHE 1137 if ( cache_config_file != NULL ) { 1138 int opt; 1139 1140 if ( lcache_init( ld, cache_config_file ) != 0 ) { 1141 exit( ldaptool_print_lderror( ld, cache_config_file, 1142 LDAPTOOL_CHECK4SSL_NEVER )); 1143 } 1144 opt = 1; 1145 (void) ldap_set_option( ld, LDAP_OPT_CACHE_ENABLE, &opt ); 1146 opt = LDAP_CACHE_LOCALDB; 1147 (void) ldap_set_option( ld, LDAP_OPT_CACHE_STRATEGY, &opt ); 1148 if ( ldversion == -1 ) { /* not set with -V */ 1149 ldversion = LDAP_VERSION2; /* local db only supports v2 */ 1150 } 1151 } 1152 #endif 1153 1154 1155 ldap_set_option( ld, LDAP_OPT_REFERRALS, chase_referrals ? LDAP_OPT_ON: 1156 LDAP_OPT_OFF ); 1157 if ( chase_referrals ) { 1158 ldap_set_rebind_proc( ld, get_rebind_credentials, NULL ); 1159 ldap_set_option( ld, LDAP_OPT_REFERRAL_HOP_LIMIT, &refhoplim ); 1160 } 1161 1162 if ( ldversion == -1 ) { /* not set with -V and not using local db */ 1163 ldversion = LDAP_VERSION3; 1164 } 1165 ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion ); 1166 1167 return( ld ); 1168 } 1169 1170 1171 /* 1172 * perform a bind to the LDAP server if needed. 1173 * if an error occurs, we exit here. 1174 */ 1175 void 1176 ldaptool_bind( LDAP *ld ) 1177 { 1178 int rc; 1179 char *conv; 1180 LDAPControl auth_resp_ctrl, *ctrl_array[ 2 ], **bindctrls; 1181 #ifdef HAVE_SASL_OPTIONS 1182 void *defaults; 1183 #endif 1184 1185 if ( ldaptool_not ) { 1186 return; 1187 } 1188 1189 if ( send_auth_response_ctrl ) { 1190 auth_resp_ctrl.ldctl_oid = LDAP_CONTROL_AUTH_REQUEST; 1191 auth_resp_ctrl.ldctl_value.bv_val = NULL; 1192 auth_resp_ctrl.ldctl_value.bv_len = 0; 1193 auth_resp_ctrl.ldctl_iscritical = 0; 1194 1195 ctrl_array[0] = &auth_resp_ctrl; 1196 ctrl_array[1] = NULL; 1197 bindctrls = ctrl_array; 1198 } else { 1199 bindctrls = NULL; 1200 } 1201 1202 /* 1203 * if using LDAPv3 and not using client auth., omit NULL bind for 1204 * efficiency. 1205 */ 1206 if ( ldversion > LDAP_VERSION2 && binddn == NULL && passwd == NULL 1207 && ssl_certname == NULL ) { 1208 #ifdef HAVE_SASL_OPTIONS 1209 if ( ldapauth != LDAP_AUTH_SASL ) { 1210 return; 1211 } 1212 #else 1213 return; 1214 #endif 1215 } 1216 1217 /* 1218 * do the bind, backing off one LDAP version if necessary 1219 */ 1220 conv = ldaptool_local2UTF8( binddn ); 1221 1222 #ifdef HAVE_SASL_OPTIONS 1223 if ( ldapauth == LDAP_AUTH_SASL) { 1224 if ( sasl_mech == NULL) { 1225 fprintf( stderr, gettext("Please specify the SASL mechanism name when " 1226 "using SASL options\n")); 1227 return; 1228 } 1229 1230 if ( sasl_secprops != NULL) { 1231 rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS, 1232 (void *) sasl_secprops ); 1233 1234 if ( rc != LDAP_SUCCESS ) { 1235 fprintf( stderr, gettext("Unable to set LDAP_OPT_X_SASL_SECPROPS: %s\n"), 1236 sasl_secprops ); 1237 return; 1238 } 1239 } 1240 1241 defaults = ldaptool_set_sasl_defaults( ld, sasl_mech, sasl_authid, sasl_username, passwd, sasl_realm ); 1242 if (defaults == NULL) { 1243 perror ("malloc"); 1244 exit (LDAP_NO_MEMORY); 1245 } 1246 1247 rc = ldap_sasl_interactive_bind_s( ld, binddn, sasl_mech, NULL, NULL, 1248 sasl_flags, ldaptool_sasl_interact, defaults ); 1249 1250 if (rc != LDAP_SUCCESS ) { 1251 ldap_perror( ld, "ldap_sasl_interactive_bind_s" ); 1252 } 1253 } else 1254 #endif /* HAVE_SASL_OPTIONS */ 1255 /* 1256 * if using LDAPv3 and client auth., try a SASL EXTERNAL bind 1257 */ 1258 if ( ldversion > LDAP_VERSION2 && binddn == NULL && passwd == NULL 1259 && ssl_certname != NULL ) { 1260 rc = ldaptool_sasl_bind_s( ld, NULL, LDAP_SASL_EXTERNAL, NULL, 1261 bindctrls, NULL, NULL, "ldap_sasl_bind" ); 1262 } 1263 else { 1264 rc = ldaptool_simple_bind_s( ld, conv, passwd, bindctrls, NULL, 1265 "ldap_simple_bind" ); 1266 } 1267 1268 if ( rc == LDAP_SUCCESS ) { 1269 if ( conv != NULL ) { 1270 free( conv ); 1271 } 1272 return; /* success */ 1273 } 1274 1275 #ifdef HAVE_SASL_OPTIONS 1276 if (ldapauth != LDAP_AUTH_SASL) { 1277 #endif /* HAVE_SASL_OPTIONS */ 1278 if ( rc == LDAP_PROTOCOL_ERROR && ldversion > LDAP_VERSION2 ) { 1279 /* 1280 * try again, backing off one LDAP version 1281 * this is okay even for client auth. because the way to achieve 1282 * client auth. with LDAPv2 is to perform a NULL simple bind. 1283 */ 1284 --ldversion; 1285 fprintf( stderr, gettext("%s: the server doesn't understand LDAPv%d;" 1286 " trying LDAPv%d instead...\n"), ldaptool_progname, 1287 ldversion + 1, ldversion ); 1288 ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &ldversion ); 1289 if (( rc = ldaptool_simple_bind_s( ld, conv, passwd, 1290 bindctrls, NULL, "ldap_simple_bind" )) == LDAP_SUCCESS ) { 1291 if( conv != NULL ) 1292 free( conv ); 1293 return; /* a qualified success */ 1294 } 1295 } 1296 #ifdef HAVE_SASL_OPTIONS 1297 } 1298 #endif /* HAVE_SASL_OPTIONS */ 1299 1300 if ( conv != NULL ) { 1301 free( conv ); 1302 } 1303 1304 /* 1305 * bind(s) failed -- fatal error 1306 */ 1307 ldap_unbind( ld ); 1308 exit( rc ); 1309 } 1310 1311 1312 /* 1313 * close open files, unbind, etc. 1314 */ 1315 void 1316 ldaptool_cleanup( LDAP *ld ) 1317 { 1318 if ( ld != NULL ) { 1319 ldap_unbind( ld ); 1320 } 1321 1322 if ( ldaptool_fp != NULL && ldaptool_fp != stdin ) { 1323 fclose( ldaptool_fp ); 1324 ldaptool_fp = NULL; 1325 } 1326 } 1327 1328 1329 /* 1330 * Retrieve and print an LDAP error message. Returns the LDAP error code. 1331 */ 1332 int 1333 ldaptool_print_lderror( LDAP *ld, char *msg, int check4ssl ) 1334 { 1335 int lderr = ldap_get_lderrno( ld, NULL, NULL ); 1336 1337 ldap_perror( ld, msg ); 1338 #ifndef SOLARIS_LDAP_CMD 1339 if ( secure && check4ssl != LDAPTOOL_CHECK4SSL_NEVER ) { 1340 if ( check4ssl == LDAPTOOL_CHECK4SSL_ALWAYS 1341 || ( lderr == LDAP_SERVER_DOWN )) { 1342 int sslerr = PORT_GetError(); 1343 1344 fprintf( stderr, gettext("\tSSL error %d (%s)\n"), sslerr, 1345 ldapssl_err2string( sslerr )); 1346 } 1347 } 1348 #endif /* SOLARIS_LDAP_CMD */ 1349 1350 return( lderr ); 1351 } 1352 1353 1354 /* 1355 * print referrals to stderr 1356 */ 1357 void 1358 ldaptool_print_referrals( char **refs ) 1359 { 1360 int i; 1361 1362 if ( refs != NULL ) { 1363 for ( i = 0; refs[ i ] != NULL; ++i ) { 1364 fprintf( stderr, gettext("Referral: %s\n"), refs[ i ] ); 1365 } 1366 } 1367 } 1368 1369 1370 /* 1371 * print contents of an extended response to stderr 1372 * this is mainly to support unsolicited notifications 1373 * Returns an LDAP error code (from the extended result). 1374 */ 1375 int 1376 ldaptool_print_extended_response( LDAP *ld, LDAPMessage *res, char *msg ) 1377 { 1378 char *oid; 1379 struct berval *data; 1380 1381 if ( ldap_parse_extended_result( ld, res, &oid, &data, 0 ) 1382 != LDAP_SUCCESS ) { 1383 ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP ); 1384 } else { 1385 if ( oid != NULL ) { 1386 if ( strcmp ( oid, LDAP_NOTICE_OF_DISCONNECTION ) == 0 ) { 1387 fprintf( stderr, gettext("%s: Notice of Disconnection\n"), msg ); 1388 } else { 1389 fprintf( stderr, gettext("%s: OID %s\n"), msg, oid ); 1390 } 1391 ldap_memfree( oid ); 1392 } else { 1393 fprintf( stderr, gettext("%s: missing OID\n"), msg ); 1394 } 1395 1396 if ( data != NULL ) { 1397 fprintf( stderr, gettext("%s: Data (length %ld):\n"), msg, data->bv_len ); 1398 #if 0 1399 /* XXXmcs: maybe we should display the actual data? */ 1400 lber_bprint( data->bv_val, data->bv_len ); 1401 #endif 1402 ber_bvfree( data ); 1403 } 1404 } 1405 1406 return parse_result( ld, res, NULL, msg, 1 ); 1407 } 1408 1409 1410 /* 1411 * Like ldap_sasl_bind_s() but calls wait4result() to display 1412 * any referrals returned and report errors in a consistent way. 1413 */ 1414 int 1415 ldaptool_sasl_bind_s( LDAP *ld, const char *dn, const char *mechanism, 1416 const struct berval *cred, LDAPControl **serverctrls, 1417 LDAPControl **clientctrls, struct berval **servercredp, char *msg ) 1418 { 1419 int rc, msgid; 1420 1421 if ( servercredp != NULL ) { 1422 *servercredp = NULL; 1423 } 1424 1425 if (( rc = ldap_sasl_bind( ld, dn, mechanism, cred, serverctrls, 1426 clientctrls, &msgid )) != LDAP_SUCCESS ) { 1427 ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP ); 1428 } else { 1429 rc = wait4result( ld, msgid, servercredp, msg ); 1430 } 1431 1432 return( rc ); 1433 } 1434 1435 1436 /* 1437 * Like ldap_simple_bind_s() but calls wait4result() to display 1438 * any referrals returned and report errors in a consistent way. 1439 */ 1440 int 1441 ldaptool_simple_bind_s( LDAP *ld, const char *dn, const char *passwd, 1442 LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg ) 1443 { 1444 struct berval bv; 1445 1446 bv.bv_val = (char *)passwd; /* XXXmcs: had to cast away const */ 1447 bv.bv_len = ( passwd == NULL ? 0 : strlen( passwd )); 1448 return( ldaptool_sasl_bind_s( ld, dn, LDAP_SASL_SIMPLE, &bv, serverctrls, 1449 clientctrls, NULL, msg )); 1450 } 1451 1452 1453 /* 1454 * Like ldap_add_ext_s() but calls wait4result() to display 1455 * any referrals returned and report errors in a consistent way. 1456 */ 1457 int 1458 ldaptool_add_ext_s( LDAP *ld, const char *dn, LDAPMod **attrs, 1459 LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg ) 1460 { 1461 int rc, msgid; 1462 1463 if (( rc = ldap_add_ext( ld, dn, attrs, serverctrls, clientctrls, &msgid )) 1464 != LDAP_SUCCESS ) { 1465 ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP ); 1466 } else { 1467 /* 1468 * 25-April-2000 Note: the next line used to read: 1469 * rc = wait4result( ld, msgid, NULL, msg ); 1470 * 'msgid' it was changed to 'LDAP_RES_ANY' in order to receive 1471 * unsolicited notifications. 1472 */ 1473 rc = wait4result( ld, LDAP_RES_ANY, NULL, msg ); 1474 } 1475 1476 return( rc ); 1477 } 1478 1479 1480 /* 1481 * Like ldap_modify_ext_s() but calls wait4result() to display 1482 * any referrals returned and report errors in a consistent way. 1483 */ 1484 int 1485 ldaptool_modify_ext_s( LDAP *ld, const char *dn, LDAPMod **mods, 1486 LDAPControl **serverctrls, LDAPControl **clientctrls, char *msg ) 1487 { 1488 int rc, msgid; 1489 1490 if (( rc = ldap_modify_ext( ld, dn, mods, serverctrls, clientctrls, 1491 &msgid )) != LDAP_SUCCESS ) { 1492 ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP ); 1493 } else { 1494 rc = wait4result( ld, msgid, NULL, msg ); 1495 } 1496 1497 return( rc ); 1498 } 1499 1500 1501 /* 1502 * Like ldap_delete_ext_s() but calls wait4result() to display 1503 * any referrals returned and report errors in a consistent way. 1504 */ 1505 int 1506 ldaptool_delete_ext_s( LDAP *ld, const char *dn, LDAPControl **serverctrls, 1507 LDAPControl **clientctrls, char *msg ) 1508 { 1509 int rc, msgid; 1510 1511 if (( rc = ldap_delete_ext( ld, dn, serverctrls, clientctrls, &msgid )) 1512 != LDAP_SUCCESS ) { 1513 ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP ); 1514 } else { 1515 rc = wait4result( ld, msgid, NULL, msg ); 1516 } 1517 1518 return( rc ); 1519 } 1520 1521 1522 /* 1523 * Like ldap_compare_ext_s() but calls wait4result() to display 1524 * any referrals returned and report errors in a consistent way. 1525 */ 1526 int ldaptool_compare_ext_s( LDAP *ld, const char *dn, const char *attrtype, 1527 const struct berval *bvalue, LDAPControl **serverctrls, 1528 LDAPControl **clientctrls, char *msg ) 1529 { 1530 int rc, msgid; 1531 1532 if (( rc = ldap_compare_ext( ld, dn, attrtype, bvalue, serverctrls, 1533 clientctrls, &msgid )) != LDAP_SUCCESS ) { 1534 ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP ); 1535 } else { 1536 rc = wait4result( ld, msgid, NULL, msg ); 1537 } 1538 1539 return( rc ); 1540 } 1541 1542 1543 /* 1544 * Like ldap_rename_s() but calls wait4result() to display 1545 * any referrals returned and report errors in a consistent way. 1546 */ 1547 int 1548 ldaptool_rename_s( LDAP *ld, const char *dn, const char *newrdn, 1549 const char *newparent, int deleteoldrdn, LDAPControl **serverctrls, 1550 LDAPControl **clientctrls, char *msg ) 1551 { 1552 int rc, msgid; 1553 1554 if (( rc = ldap_rename( ld, dn, newrdn, newparent, deleteoldrdn, 1555 serverctrls, clientctrls, &msgid )) != LDAP_SUCCESS ) { 1556 ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP ); 1557 } else { 1558 rc = wait4result( ld, msgid, NULL, msg ); 1559 } 1560 1561 return( rc ); 1562 } 1563 1564 1565 /* 1566 * Wait for a result, check for and display errors and referrals. 1567 * Also recognize and display "Unsolicited notification" messages. 1568 * Returns an LDAP error code. 1569 */ 1570 static int 1571 wait4result( LDAP *ld, int msgid, struct berval **servercredp, char *msg ) 1572 { 1573 LDAPMessage *res; 1574 int rc, received_only_unsolicited = 1; 1575 1576 while ( received_only_unsolicited ) { 1577 res = NULL; 1578 if (( rc = ldap_result( ld, msgid, 1, (struct timeval *)NULL, &res )) 1579 == -1 ) { 1580 ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP ); 1581 return( ldap_get_lderrno( ld, NULL, NULL )); 1582 } 1583 1584 /* 1585 * Special handling for unsolicited notifications: 1586 * 1. Parse and display contents. 1587 * 2. go back and wait for another (real) result. 1588 */ 1589 if ( rc == LDAP_RES_EXTENDED 1590 && ldap_msgid( res ) == LDAP_RES_UNSOLICITED ) { 1591 rc = ldaptool_print_extended_response( ld, res, 1592 "Unsolicited response" ); 1593 } else { 1594 rc = parse_result( ld, res, servercredp, msg, 1 ); 1595 received_only_unsolicited = 0; /* we're done */ 1596 } 1597 } 1598 1599 return( rc ); 1600 } 1601 1602 1603 static int 1604 parse_result( LDAP *ld, LDAPMessage *res, struct berval **servercredp, 1605 char *msg, int freeit ) 1606 { 1607 int rc, lderr, errno; 1608 int pw_days=0, pw_hrs=0, pw_mins=0, pw_secs=0; /* for pwpolicy */ 1609 char **refs = NULL; 1610 LDAPControl **ctrls; 1611 1612 if (( rc = ldap_parse_result( ld, res, &lderr, NULL, NULL, &refs, 1613 &ctrls, 0 )) != LDAP_SUCCESS ) { 1614 ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP ); 1615 ldap_msgfree( res ); 1616 return( rc ); 1617 } 1618 1619 /* check for authentication response control & PWPOLICY control*/ 1620 if ( NULL != ctrls ) { 1621 int i; 1622 char *s; 1623 1624 for ( i = 0; NULL != ctrls[i]; ++i ) { 1625 if ( 0 == strcmp( ctrls[i]->ldctl_oid, 1626 LDAP_CONTROL_AUTH_RESPONSE )) { 1627 s = ctrls[i]->ldctl_value.bv_val; 1628 if ( NULL == s ) { 1629 s = "Null"; 1630 } else if ( *s == '\0' ) { 1631 s = "Anonymous"; 1632 } 1633 fprintf( stderr, gettext("%s: bound as %s\n"), ldaptool_progname, s ); 1634 } 1635 1636 if ( 0 == strcmp( ctrls[i]->ldctl_oid, 1637 LDAP_CONTROL_PWEXPIRING )) { 1638 1639 /* Warn the user his passwd is to expire */ 1640 errno = 0; 1641 pw_secs = atoi(ctrls[i]->ldctl_value.bv_val); 1642 if ( pw_secs > 0 && errno != ERANGE ) { 1643 if ( pw_secs > 86400 ) { 1644 pw_days = ( pw_secs / 86400 ); 1645 pw_secs = ( pw_secs % 86400 ); 1646 } 1647 if ( pw_secs > 3600 ) { 1648 pw_hrs = ( pw_secs / 3600 ); 1649 pw_secs = ( pw_secs % 3600 ); 1650 } 1651 if ( pw_secs > 60 ) { 1652 pw_mins = ( pw_secs / 60 ); 1653 pw_secs = ( pw_secs % 60 ); 1654 } 1655 1656 printf(gettext("%s: Warning ! Your password will expire after "), ldaptool_progname); 1657 if ( pw_days ) { 1658 printf (gettext("%d days, "), pw_days); 1659 } 1660 if ( pw_hrs ) { 1661 printf (gettext("%d hrs, "), pw_hrs); 1662 } 1663 if ( pw_mins ) { 1664 printf (gettext("%d mins, "), pw_mins); 1665 } 1666 printf(gettext("%d seconds.\n"), pw_secs); 1667 1668 } 1669 } 1670 } 1671 ldap_controls_free( ctrls ); 1672 } 1673 1674 if ( servercredp != NULL && ( rc = ldap_parse_sasl_bind_result( ld, res, 1675 servercredp, 0 )) != LDAP_SUCCESS ) { 1676 ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP ); 1677 ldap_msgfree( res ); 1678 return( rc ); 1679 } 1680 1681 if ( freeit ) { 1682 ldap_msgfree( res ); 1683 } 1684 1685 if ( LDAPTOOL_RESULT_IS_AN_ERROR( lderr )) { 1686 ldaptool_print_lderror( ld, msg, LDAPTOOL_CHECK4SSL_IF_APPROP ); 1687 } 1688 1689 if ( refs != NULL ) { 1690 ldaptool_print_referrals( refs ); 1691 ldap_value_free( refs ); 1692 } 1693 1694 return( lderr ); 1695 } 1696 1697 1698 /* 1699 * if -M was passed on the command line, create and return a "Manage DSA IT" 1700 * LDAPv3 control. If not, return NULL. 1701 */ 1702 LDAPControl * 1703 ldaptool_create_manage_dsait_control( void ) 1704 { 1705 LDAPControl *ctl; 1706 1707 if ( !send_manage_dsait_ctrl ) { 1708 return( NULL ); 1709 } 1710 1711 if (( ctl = (LDAPControl *)calloc( 1, sizeof( LDAPControl ))) == NULL || 1712 ( ctl->ldctl_oid = strdup( LDAP_CONTROL_MANAGEDSAIT )) == NULL ) { 1713 perror( "calloc" ); 1714 exit( LDAP_NO_MEMORY ); 1715 } 1716 1717 ctl->ldctl_iscritical = 1; 1718 1719 return( ctl ); 1720 } 1721 1722 /* 1723 * if -y "dn" was supplied on the command line, create the control 1724 */ 1725 LDAPControl * 1726 ldaptool_create_proxyauth_control( LDAP *ld ) 1727 { 1728 LDAPControl *ctl = NULL; 1729 int rc; 1730 1731 1732 if ( !proxyauth_id) 1733 return( NULL ); 1734 1735 if ( 2 == proxyauth_version ) { 1736 rc = ldap_create_proxiedauth_control( ld, proxyauth_id, &ctl); 1737 } else { 1738 rc = ldap_create_proxyauth_control( ld, proxyauth_id, 1, &ctl); 1739 } 1740 if ( rc != LDAP_SUCCESS) 1741 { 1742 if (ctl) 1743 ldap_control_free( ctl); 1744 return NULL; 1745 } 1746 return( ctl ); 1747 } 1748 1749 #ifndef SOLARIS_LDAP_CMD 1750 LDAPControl * 1751 ldaptool_create_geteffectiveRights_control ( LDAP *ld, const char *authzid, 1752 const char **attrlist) 1753 { 1754 LDAPControl *ctl = NULL; 1755 int rc; 1756 1757 rc = ldap_create_geteffectiveRights_control( ld, authzid, attrlist, 1, 1758 &ctl); 1759 1760 if ( rc != LDAP_SUCCESS) 1761 { 1762 if (ctl) 1763 ldap_control_free( ctl); 1764 return NULL; 1765 } 1766 return( ctl ); 1767 } 1768 #endif /* SOLARIS_LDAP_CMD */ 1769 1770 1771 void 1772 ldaptool_add_control_to_array( LDAPControl *ctrl, LDAPControl **array) 1773 { 1774 1775 int i; 1776 for (i=0; i< CONTROL_REQUESTS; i++) 1777 { 1778 if (*(array + i) == NULL) 1779 { 1780 *(array + i +1) = NULL; 1781 *(array + i) = ctrl; 1782 return ; 1783 } 1784 } 1785 fprintf(stderr, gettext("%s: failed to store request control!!!!!!\n"), 1786 ldaptool_progname); 1787 } 1788 1789 /* 1790 * Dispose of all controls in array and prepare array for reuse. 1791 */ 1792 void 1793 ldaptool_reset_control_array( LDAPControl **array ) 1794 { 1795 int i; 1796 1797 for ( i = 0; i < CONTROL_REQUESTS; i++ ) { 1798 if ( array[i] != NULL ) { 1799 ldap_control_free( array[i] ); 1800 array[i] = NULL; 1801 } 1802 } 1803 } 1804 1805 /* 1806 * This function calculates control value and its length. *value can 1807 * be pointing to plain value, ":b64encoded value" or "<fileurl". 1808 */ 1809 static int 1810 calculate_ctrl_value( const char *value, 1811 char **ctrl_value, int *vlen) 1812 { 1813 int b64; 1814 if (*value == ':') { 1815 value++; 1816 b64 = 1; 1817 } else { 1818 b64 = 0; 1819 } 1820 *ctrl_value = (char *)value; 1821 1822 if ( b64 ) { 1823 if (( *vlen = ldif_base64_decode( (char *)value, 1824 (unsigned char *)value )) < 0 ) { 1825 fprintf( stderr, 1826 gettext("Unable to decode base64 control value \"%s\"\n"), value); 1827 return( -1 ); 1828 } 1829 } else { 1830 *vlen = (int)strlen(*ctrl_value); 1831 } 1832 return( 0 ); 1833 } 1834 1835 /* 1836 * Parse the optarg from -J option of ldapsearch 1837 * and within LDIFfile for ldapmodify. Take ctrl_arg 1838 * (the whole string) and divide it into oid, criticality 1839 * and value. This function breaks down original ctrl_arg 1840 * with '\0' in places. Also, calculate length of valuestring. 1841 */ 1842 int 1843 ldaptool_parse_ctrl_arg(char *ctrl_arg, char sep, 1844 char **ctrl_oid, int *ctrl_criticality, 1845 char **ctrl_value, int *vlen) 1846 { 1847 char *s, *p; 1848 int strict; 1849 1850 /* Initialize passed variables with default values */ 1851 *ctrl_oid = *ctrl_value = NULL; 1852 *ctrl_criticality = 0; 1853 *vlen = 0; 1854 1855 strict = (sep == ' ' ? 1 : 0); 1856 if(!(s=strchr(ctrl_arg, sep))) { 1857 /* Possible values of ctrl_arg are 1858 * oid[:value|::b64value|:<fileurl] within LDIF, i.e. sep=' ' 1859 * oid from command line option, i.e. sep=':' 1860 */ 1861 if (sep == ' ') { 1862 if (!(s=strchr(ctrl_arg, ':'))) { 1863 *ctrl_oid = ctrl_arg; 1864 } 1865 else { 1866 /* ctrl_arg is of oid:[value|:b64value|<fileurl] 1867 * form in the LDIF record. So, grab the oid and then 1868 * jump to continue the parsing of ctrl_arg. 1869 * 's' is pointing just after oid ends. 1870 */ 1871 *s++ = '\0'; 1872 *ctrl_oid = ctrl_arg; 1873 return (calculate_ctrl_value( s, ctrl_value, vlen )); 1874 } 1875 } else { 1876 /* oid - from command line option, i.e. sep=':' */ 1877 *ctrl_oid = ctrl_arg; 1878 } 1879 } 1880 else { 1881 /* Possible values of ctrl_arg are 1882 * oid:criticality[:value|::b64value|:<fileurl] - command line 1883 * oid criticality[:value|::b64value|:<fileurl] - LDIF 1884 * And 's' is pointing just after oid ends. 1885 */ 1886 1887 if (*(s+1) == '\0') { 1888 fprintf( stderr, gettext("missing value\n") ); 1889 return( -1 ); 1890 } 1891 *s = '\0'; 1892 *ctrl_oid = ctrl_arg; 1893 p = ++s; 1894 if(!(s=strchr(p, ':'))) { 1895 if ( (*ctrl_criticality = ldaptool_boolean_str2value(p, strict)) 1896 == -1 ) { 1897 fprintf( stderr, gettext("Invalid criticality value\n") ); 1898 return( -1 ); 1899 } 1900 } 1901 else { 1902 if (*(s+1) == '\0') { 1903 fprintf( stderr, gettext("missing value\n") ); 1904 return ( -1 ); 1905 } 1906 *s++ = '\0'; 1907 if ( (*ctrl_criticality = ldaptool_boolean_str2value(p, strict)) 1908 == -1 ) { 1909 fprintf( stderr, gettext("Invalid criticality value\n") ); 1910 return ( -1 ); 1911 } 1912 return (calculate_ctrl_value( s, ctrl_value, vlen )); 1913 } 1914 } 1915 1916 return( 0 ); 1917 } 1918 1919 1920 /* 1921 * callback function for LDAP bind credentials 1922 */ 1923 static int 1924 LDAP_CALL 1925 LDAP_CALLBACK 1926 get_rebind_credentials( LDAP *ld, char **whop, char **credp, 1927 int *methodp, int freeit, void* arg ) 1928 { 1929 if ( !freeit ) { 1930 *whop = binddn; 1931 *credp = passwd; 1932 *methodp = LDAP_AUTH_SIMPLE; 1933 } 1934 1935 return( LDAP_SUCCESS ); 1936 } 1937 1938 1939 /* 1940 * return pointer to pathname to temporary directory. 1941 * First we see if the environment variable "TEMP" is set and use it. 1942 * Then we see if the environment variable "TMP" is set and use it. 1943 * If this fails, we use "/tmp" on UNIX and fail on Windows. 1944 */ 1945 char * 1946 ldaptool_get_tmp_dir( void ) 1947 { 1948 char *p; 1949 int offset; 1950 1951 if (( p = getenv( "TEMP" )) == NULL && ( p = getenv( "TMP" )) == NULL ) { 1952 #ifdef _WINDOWS 1953 fprintf( stderr, gettext("%s: please set the TEMP environment variable.\n"), 1954 ldaptool_progname ); 1955 exit( LDAP_LOCAL_ERROR ); 1956 #else 1957 return( "/tmp" ); /* last resort on UNIX */ 1958 #endif 1959 } 1960 1961 /* 1962 * remove trailing slash if present 1963 */ 1964 offset = strlen( p ) - 1; 1965 if ( p[offset] == '/' 1966 #ifdef _WINDOWS 1967 || p[offset] == '\\' 1968 #endif 1969 ) { 1970 if (( p = strdup( p )) == NULL ) { 1971 perror( "strdup" ); 1972 exit( LDAP_NO_MEMORY ); 1973 } 1974 1975 p[offset] = '\0'; 1976 } 1977 1978 return( p ); 1979 } 1980 1981 1982 int 1983 ldaptool_berval_is_ascii( const struct berval *bvp ) 1984 { 1985 unsigned long j; 1986 int is_ascii = 1; /* optimistic */ 1987 1988 for ( j = 0; j < bvp->bv_len; ++j ) { 1989 if ( !isascii( bvp->bv_val[ j ] )) { 1990 is_ascii = 0; 1991 break; 1992 } 1993 } 1994 1995 return( is_ascii ); 1996 } 1997 1998 1999 #ifdef LDAP_DEBUG_MEMORY 2000 #define LDAPTOOL_ALLOC_FREED 0xF001 2001 #define LDAPTOOL_ALLOC_INUSE 0xF002 2002 2003 static void * 2004 ldaptool_debug_alloc( void *ptr, size_t size ) 2005 { 2006 int *statusp; 2007 void *systemptr; 2008 2009 if ( ptr == NULL ) { 2010 systemptr = NULL; 2011 } else { 2012 systemptr = (void *)((char *)ptr - sizeof(int)); 2013 } 2014 2015 if (( statusp = (int *)realloc( systemptr, size + sizeof(int))) == NULL ) { 2016 fprintf( stderr, gettext("%s: realloc( 0x%x, %d) failed\n"), 2017 ldaptool_progname, systemptr, size ); 2018 return( NULL ); 2019 } 2020 2021 *statusp = LDAPTOOL_ALLOC_INUSE; 2022 2023 return( (char *)statusp + sizeof(int)); 2024 } 2025 2026 2027 static void * 2028 ldaptool_debug_realloc( void *ptr, size_t size ) 2029 { 2030 void *p; 2031 2032 if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) { 2033 fprintf( stderr, gettext("%s: => realloc( 0x%x, %d )\n"), 2034 ldaptool_progname, ptr, size ); 2035 } 2036 2037 p = ldaptool_debug_alloc( ptr, size ); 2038 2039 if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) { 2040 fprintf( stderr, gettext("%s: 0x%x <= realloc()\n"), ldaptool_progname, p ); 2041 } 2042 2043 return( p ); 2044 } 2045 2046 2047 static void * 2048 ldaptool_debug_malloc( size_t size ) 2049 { 2050 void *p; 2051 2052 if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) { 2053 fprintf( stderr, gettext("%s: => malloc( %d)\n"), ldaptool_progname, size ); 2054 } 2055 2056 p = ldaptool_debug_alloc( NULL, size ); 2057 2058 if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) { 2059 fprintf( stderr, gettext("%s: 0x%x <= malloc()\n"), ldaptool_progname, p ); 2060 } 2061 2062 return( p ); 2063 } 2064 2065 2066 static void * 2067 ldaptool_debug_calloc( size_t nelem, size_t elsize ) 2068 { 2069 void *p; 2070 2071 if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) { 2072 fprintf( stderr, gettext("%s: => calloc( %d, %d )\n"), 2073 ldaptool_progname, nelem, elsize ); 2074 } 2075 2076 if (( p = ldaptool_debug_alloc( NULL, nelem * elsize )) != NULL ) { 2077 memset( p, 0, nelem * elsize ); 2078 } 2079 2080 if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) { 2081 fprintf( stderr, gettext("%s: 0x%x <= calloc()\n"), ldaptool_progname, p ); 2082 } 2083 2084 return( p ); 2085 } 2086 2087 2088 static void 2089 ldaptool_debug_free( void *ptr ) 2090 { 2091 int *statusp = (int *)((char *)ptr - sizeof(int)); 2092 2093 if ( ldaptool_dbg_lvl & LDAP_DEBUG_TRACE ) { 2094 fprintf( stderr, gettext("%s: => free( 0x%x )\n"), ldaptool_progname, ptr ); 2095 } 2096 2097 if ( ptr == NULL ) { 2098 fprintf( stderr, gettext("%s: bad free( 0x0 ) attempted (NULL pointer)\n"), 2099 ldaptool_progname ); 2100 } else if ( *statusp != LDAPTOOL_ALLOC_INUSE ) { 2101 fprintf( stderr, gettext("%s: bad free( 0x%x ) attempted" 2102 " (block not in use; status is %d)\n"), 2103 ldaptool_progname, ptr, *statusp ); 2104 } else { 2105 *statusp = LDAPTOOL_ALLOC_FREED; 2106 free( statusp ); 2107 } 2108 } 2109 #endif /* LDAP_DEBUG_MEMORY */ 2110 2111 2112 #if defined(NET_SSL) 2113 /* 2114 * Derive key database path from certificate database path and return a 2115 * malloc'd string. 2116 * 2117 * We just return an exact copy of "certdbpath" unless it ends in "cert.db", 2118 * "cert5.db", or "cert7.db". In those cases we strip off everything from 2119 * "cert" on and append "key.db", "key5.db", or "key3.db" as appropriate. 2120 * Strangely enough cert7.db and key3.db go together. 2121 */ 2122 static char * 2123 certpath2keypath( char *certdbpath ) 2124 { 2125 char *keydbpath, *appendstr; 2126 int len, striplen; 2127 2128 if ( certdbpath == NULL ) { 2129 return( NULL ); 2130 } 2131 2132 if (( keydbpath = strdup( certdbpath )) == NULL ) { 2133 perror( "strdup" ); 2134 exit( LDAP_NO_MEMORY ); 2135 } 2136 2137 len = strlen( keydbpath ); 2138 if ( len > 7 && 2139 strcasecmp( "cert.db", keydbpath + len - 7 ) == 0 ) { 2140 striplen = 7; 2141 appendstr = "key.db"; 2142 2143 } else if ( len > 8 && 2144 strcasecmp( "cert5.db", keydbpath + len - 8 ) == 0 ) { 2145 striplen = 8; 2146 appendstr = "key5.db"; 2147 } else if ( len > 8 && 2148 strcasecmp( "cert7.db", keydbpath + len - 8 ) == 0 ) { 2149 striplen = 8; 2150 appendstr = "key3.db"; 2151 } else { 2152 striplen = 0; 2153 } 2154 2155 if ( striplen > 0 ) { 2156 /* 2157 * The following code assumes that strlen( appendstr ) < striplen! 2158 */ 2159 strcpy( keydbpath + len - striplen, appendstr ); 2160 } 2161 2162 return( keydbpath ); 2163 } 2164 2165 #ifdef LDAP_TOOL_PKCS11 2166 static 2167 char * 2168 buildTokenCertName( const char *tokenName, const char *certName) 2169 { 2170 2171 int tokenlen = strlen(tokenName); 2172 int len = tokenlen + strlen(certName) +2; 2173 char *result; 2174 2175 if (( result = malloc( len )) != NULL) { 2176 strcpy(result, tokenName); 2177 *(result+tokenlen) = ':'; 2178 ++tokenlen; 2179 strcpy(result+tokenlen, certName); 2180 } else { 2181 perror("malloc"); 2182 exit( LDAP_NO_MEMORY ); 2183 } 2184 return result; 2185 } 2186 2187 2188 2189 static 2190 int 2191 ldaptool_getcertpath( void *context, char **certlocp ) 2192 { 2193 2194 *certlocp = ssl_certdbpath; 2195 if ( ldaptool_verbose ) { 2196 if (ssl_certdbpath) 2197 { 2198 printf(gettext("ldaptool_getcertpath -- %s\n"), ssl_certdbpath ); 2199 } 2200 else 2201 { 2202 printf(gettext("ldaptool_getcertpath -- (null)\n")); 2203 } 2204 2205 } 2206 return LDAP_SUCCESS; 2207 } 2208 2209 int 2210 ldaptool_getcertname( void *context, char **certnamep ) 2211 { 2212 2213 *certnamep = ssl_certname; 2214 if ( ldaptool_verbose ) { 2215 if (ssl_certname) 2216 { 2217 printf(gettext("ldaptool_getcertname -- %s\n"), *certnamep); 2218 } 2219 else 2220 { 2221 printf(gettext("ldaptool_getcertname -- (null)\n")); 2222 } 2223 } 2224 return LDAP_SUCCESS; 2225 } 2226 2227 int 2228 ldaptool_getkeypath(void *context, char **keylocp ) 2229 { 2230 *keylocp = ssl_keydbpath; 2231 if ( ldaptool_verbose ) { 2232 if (ssl_keydbpath) 2233 { 2234 printf(gettext("ldaptool_getkeypath -- %s\n"),*keylocp); 2235 } 2236 else 2237 { 2238 printf(gettext("ldaptool_getkeypath -- (null)\n")); 2239 } 2240 } 2241 2242 return LDAP_SUCCESS; 2243 } 2244 2245 int 2246 ldaptool_gettokenname( void *context, char **tokennamep ) 2247 { 2248 2249 *tokennamep = pkcs_token; 2250 if ( ldaptool_verbose ) { 2251 if (pkcs_token) 2252 { 2253 printf(gettext("ldaptool_gettokenname -- %s\n"),*tokennamep); 2254 } 2255 else 2256 { 2257 printf(gettext("ldaptool_gettokenname -- (null)\n")); 2258 } 2259 } 2260 2261 return LDAP_SUCCESS; 2262 } 2263 int 2264 ldaptool_gettokenpin( void *context, const char *tokennamep, char **tokenpinp) 2265 { 2266 2267 #if 0 2268 char *localtoken; 2269 #endif 2270 2271 /* XXXceb this stuff is removed for the time being. 2272 * This function should return the pin from ssl_password 2273 */ 2274 2275 2276 *tokenpinp = ssl_passwd; 2277 return LDAP_SUCCESS; 2278 2279 #if 0 2280 2281 ldaptool_gettokenname( NULL, &localtoken); 2282 2283 if (strcmp( localtoken, tokennamep)) 2284 2285 *tokenpinp = pkcs_pin; 2286 else 2287 *tokenpinp = NULL; 2288 2289 if ( ldaptool_verbose ) { 2290 if (pkcs_pin) 2291 { 2292 printf(gettext("ldaptool_getokenpin --%s\n"), tokenpinp); 2293 } 2294 else 2295 { 2296 printf(gettext("ldaptool_getokenpin -- (null)\n")); 2297 } 2298 } 2299 return LDAP_SUCCESS; 2300 #endif 2301 } 2302 2303 int 2304 ldaptool_getmodpath( void *context, char **modulep ) 2305 { 2306 *modulep = ssl_secmodpath; 2307 if ( ldaptool_verbose ) { 2308 if (ssl_secmodpath) 2309 { 2310 printf(gettext("ldaptool_getmodpath -- %s\n"), *modulep); 2311 } 2312 else 2313 { 2314 printf(gettext("ldaptool_getmodpath -- (null)\n")); 2315 } 2316 } 2317 2318 return LDAP_SUCCESS; 2319 } 2320 2321 int 2322 ldaptool_getdonglefilename( void *context, char **filename ) 2323 { 2324 *filename = ssl_donglefile; 2325 if ( ldaptool_verbose ) { 2326 if (ssl_donglefile) 2327 { 2328 printf(gettext("ldaptool_getdonglefilename -- %s\n"), *filename); 2329 } 2330 else 2331 { 2332 printf(gettext("ldaptool_getdonglefilename -- (null)\n")); 2333 } 2334 2335 } 2336 2337 return LDAP_SUCCESS; 2338 } 2339 2340 static int 2341 ldaptool_setcallbacks( struct ldapssl_pkcs_fns *pfns) 2342 { 2343 pfns->pkcs_getcertpath = (int (*)(void *, char **))ldaptool_getcertpath; 2344 pfns->pkcs_getcertname = (int (*)(void *, char **))ldaptool_getcertname; 2345 pfns->pkcs_getkeypath = (int (*)(void *, char **)) ldaptool_getkeypath; 2346 pfns->pkcs_getmodpath = (int (*)(void *, char **)) ldaptool_getmodpath; 2347 pfns->pkcs_getpin = (int (*)(void *, const char*, char **)) ldaptool_gettokenpin; 2348 pfns->pkcs_gettokenname = (int (*)(void *, char **)) ldaptool_gettokenname; 2349 pfns->pkcs_getdonglefilename = (int (*)(void *, char **)) ldaptool_getdonglefilename; 2350 pfns->local_structure_id=PKCS_STRUCTURE_ID; 2351 return LDAP_SUCCESS; 2352 } 2353 2354 2355 2356 #ifdef FORTEZZA 2357 static int 2358 ldaptool_fortezza_init( int exit_on_error ) 2359 { 2360 int rc, errcode; 2361 2362 if ( fortezza_personality == NULL && fortezza_cardmask == 0 ) { /* no FORTEZZA desired */ 2363 SSL_EnableGroup( SSL_GroupFortezza, DSFalse ); /* disable FORTEZZA */ 2364 return( 0 ); 2365 } 2366 2367 if (( rc = FortezzaConfigureServer( ldaptool_fortezza_getpin, fortezza_cardmask, 2368 fortezza_personality, ldaptool_fortezza_alert, NULL, &errcode, 2369 fortezza_krlfile )) < 0 ) { 2370 fprintf( stderr, 2371 "%s: FORTEZZA initialization failed (error %d - %s)\n", 2372 ldaptool_progname, errcode, 2373 ldaptool_fortezza_err2string( errcode )); 2374 if ( exit_on_error ) { 2375 exit( LDAP_LOCAL_ERROR ); 2376 } 2377 2378 SSL_EnableGroup( SSL_GroupFortezza, DSFalse ); /* disable FORTEZZA */ 2379 return( -1 ); 2380 } 2381 2382 SSL_EnableGroup( SSL_GroupFortezza, DSTrue ); /* enable FORTEZZA */ 2383 return( 0 ); 2384 } 2385 2386 2387 static int 2388 ldaptool_fortezza_alert( void *arg, PRBool onOpen, char *string, 2389 int value1, void *value2 ) 2390 { 2391 fprintf( stderr, "%s: FORTEZZA alert: ", ldaptool_progname ); 2392 fprintf( stderr, string, value1, value2 ); 2393 fprintf( stderr, "\n" ); 2394 return( 1 ); 2395 } 2396 2397 2398 static void * 2399 ldaptool_fortezza_getpin( char **passwordp ) 2400 { 2401 *passwordp = fortezza_pin; 2402 return( *passwordp ); 2403 } 2404 2405 2406 /* 2407 * convert a Fortezza error code (as returned by FortezzaConfigureServer() 2408 * into a human-readable string. 2409 * 2410 * Error strings are intentionally similar to those found in 2411 * ns/netsite/lib/libadmin/httpcon.c 2412 */ 2413 static char * 2414 ldaptool_fortezza_err2string( int err ) 2415 { 2416 char *s; 2417 2418 switch( err ) { 2419 case FORTEZZA_BADPASSWD: 2420 s = "invalid pin number"; 2421 break; 2422 case FORTEZZA_BADCARD: 2423 s = "bad or missing card"; 2424 break; 2425 case FORTEZZA_MISSING_KRL: 2426 s = "bad or missing compromised key list"; 2427 break; 2428 case FORTEZZA_CERT_INIT_ERROR: 2429 s = "unable to initialize certificate cache. either a cert on " 2430 "the card is bad, or an old FORTEZZA certificate is in a" 2431 "readonly database"; 2432 break; 2433 case FORTEZZA_EXPIRED_CERT: 2434 s = "unable to verify certificate"; 2435 break; 2436 default: 2437 s = "unknown error"; 2438 } 2439 2440 return( s ); 2441 } 2442 2443 #endif /* FORTEZZA */ 2444 #endif /* LDAP_TOOL_PKCS11 */ 2445 #endif /* NET_SSL */ 2446 2447 int 2448 ldaptool_boolean_str2value ( const char *ptr, int strict ) 2449 { 2450 if (strict) { 2451 if ( !(strcasecmp(ptr, "true"))) { 2452 return 1; 2453 } 2454 else if ( !(strcasecmp(ptr, "false"))) { 2455 return 0; 2456 } 2457 else { 2458 return (-1); 2459 } 2460 } 2461 else { 2462 if ( !(strcasecmp(ptr, "true")) || 2463 !(strcasecmp(ptr, "t")) || 2464 !(strcmp(ptr, "1")) ) { 2465 return (1); 2466 } 2467 else if ( !(strcasecmp(ptr, "false")) || 2468 !(strcasecmp(ptr, "f")) || 2469 !(strcmp(ptr, "0")) ) { 2470 return (0); 2471 } 2472 else { 2473 return (-1); 2474 } 2475 } 2476 } 2477 2478 FILE * 2479 ldaptool_open_file(const char *filename, const char *mode) 2480 { 2481 #ifdef _LARGEFILE64_SOURCE 2482 return fopen64(filename, mode); 2483 #else 2484 return fopen(filename, mode); 2485 #endif 2486 } 2487 2488 #ifdef later 2489 /* Functions for list in ldapdelete.c */ 2490 2491 void L_Init(Head *list) 2492 { 2493 if(list) 2494 { 2495 list->first = NULL; 2496 list->last = NULL; 2497 list->count = 0; 2498 } 2499 } 2500 2501 void L_Insert(Element *Node, Head *HeadNode) 2502 { 2503 if (!Node || !HeadNode) 2504 return; 2505 2506 Node->right = NULL; 2507 2508 if (HeadNode->first == NULL) 2509 { 2510 Node->left= NULL; 2511 HeadNode->last = HeadNode->first = Node; 2512 } 2513 else 2514 { 2515 Node->left = HeadNode->last; 2516 HeadNode->last = Node->left->right = Node; 2517 } 2518 HeadNode->count++; 2519 } 2520 2521 void L_Remove(Element *Node, Head *HeadNode) 2522 { 2523 Element *traverse = NULL; 2524 Element *prevnode = NULL; 2525 2526 if(!Node || !HeadNode) 2527 return; 2528 2529 for(traverse = HeadNode->first; traverse; traverse = traverse->right) 2530 { 2531 if(traverse == Node) 2532 { 2533 if(HeadNode->first == traverse) 2534 { 2535 HeadNode->first = traverse->right; 2536 } 2537 if(HeadNode->last == traverse) 2538 { 2539 HeadNode->last = prevnode; 2540 } 2541 traverse = traverse->right; 2542 if(prevnode != NULL) 2543 { 2544 prevnode->right = traverse; 2545 } 2546 if(traverse != NULL) 2547 { 2548 traverse->left = prevnode; 2549 } 2550 HeadNode->count--; 2551 return; 2552 } 2553 else /* traverse != node */ 2554 { 2555 prevnode = traverse; 2556 } 2557 } 2558 } 2559 #endif 2560 2561 #ifdef HAVE_SASL_OPTIONS 2562 /* 2563 * Function checks for valid args, returns an error if not found 2564 * and sets SASL params from command line 2565 */ 2566 2567 static int 2568 saslSetParam(char *saslarg) 2569 { 2570 char *attr = NULL; 2571 2572 attr = strchr(saslarg, '='); 2573 if (attr == NULL) { 2574 fprintf( stderr, gettext("Didn't find \"=\" character in %s\n"), saslarg); 2575 return (-1); 2576 } 2577 *attr = '\0'; 2578 attr++; 2579 2580 if (!strcasecmp(saslarg, "secProp")) { 2581 if ( sasl_secprops != NULL ) { 2582 fprintf( stderr, gettext("secProp previously specified\n")); 2583 return (-1); 2584 } 2585 if (( sasl_secprops = strdup(attr)) == NULL ) { 2586 perror ("malloc"); 2587 exit (LDAP_NO_MEMORY); 2588 } 2589 } else if (!strcasecmp(saslarg, "realm")) { 2590 if ( sasl_realm != NULL ) { 2591 fprintf( stderr, gettext("Realm previously specified\n")); 2592 return (-1); 2593 } 2594 if (( sasl_realm = strdup(attr)) == NULL ) { 2595 perror ("malloc"); 2596 exit (LDAP_NO_MEMORY); 2597 } 2598 } else if (!strcasecmp(saslarg, "authzid")) { 2599 if (sasl_username != NULL) { 2600 fprintf( stderr, gettext("Authorization name previously specified\n")); 2601 return (-1); 2602 } 2603 if (( sasl_username = strdup(attr)) == NULL ) { 2604 perror ("malloc"); 2605 exit (LDAP_NO_MEMORY); 2606 } 2607 } else if (!strcasecmp(saslarg, "authid")) { 2608 if ( sasl_authid != NULL ) { 2609 fprintf( stderr, gettext("Authentication name previously specified\n")); 2610 return (-1); 2611 } 2612 if (( sasl_authid = strdup(attr)) == NULL) { 2613 perror ("malloc"); 2614 exit (LDAP_NO_MEMORY); 2615 } 2616 } else if (!strcasecmp(saslarg, "mech")) { 2617 if ( sasl_mech != NULL ) { 2618 fprintf( stderr, gettext("Mech previously specified\n")); 2619 return (-1); 2620 } 2621 if (( sasl_mech = strdup(attr)) == NULL) { 2622 perror ("malloc"); 2623 exit (LDAP_NO_MEMORY); 2624 } 2625 } else { 2626 fprintf (stderr, gettext("Invalid attribute name %s\n"), saslarg); 2627 return (-1); 2628 } 2629 return 0; 2630 } 2631 #endif /* HAVE_SASL_OPTIONS */ 2632 2633 /* 2634 * check for and report input or output error on named stream 2635 * return ldap_err or ferror() (ldap_err takes precedence) 2636 * assume that fflush() already has been called if needed. 2637 * don't want to fflush() an input stream. 2638 */ 2639 int 2640 ldaptool_check_ferror(FILE * stream, const int ldap_err, const char *msg) 2641 { 2642 int err = 0; 2643 if ((err = ferror(stream)) != 0 ) { 2644 fprintf(stderr, gettext("%s: ERROR: "), ldaptool_progname); 2645 perror(msg); 2646 err = LDAP_LOCAL_ERROR; 2647 } 2648 2649 /* 2650 * reporting LDAP error code is more important than 2651 * reporting errors from ferror() 2652 */ 2653 if (ldap_err == LDAP_SUCCESS) { 2654 return(err); 2655 } else { 2656 return(ldap_err); 2657 } 2658 } 2659