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