xref: /netbsd-src/external/bsd/openldap/dist/clients/tools/ldapvc.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: ldapvc.c,v 1.2 2021/08/14 16:14:49 christos Exp $	*/
2e670fd5cSchristos 
3e670fd5cSchristos /* ldapvc.c -- a tool for verifying credentials */
4e670fd5cSchristos /* $OpenLDAP$ */
5e670fd5cSchristos /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6e670fd5cSchristos  *
7e670fd5cSchristos  * Copyright 1998-2021 The OpenLDAP Foundation.
8e670fd5cSchristos  * Portions Copyright 2010 Kurt D. Zeilenga.
9e670fd5cSchristos  * All rights reserved.
10e670fd5cSchristos  *
11e670fd5cSchristos  * Redistribution and use in source and binary forms, with or without
12e670fd5cSchristos  * modification, are permitted only as authorized by the OpenLDAP
13e670fd5cSchristos  * Public License.
14e670fd5cSchristos  *
15e670fd5cSchristos  * A copy of this license is available in the file LICENSE in the
16e670fd5cSchristos  * top-level directory of the distribution or, alternatively, at
17e670fd5cSchristos  * <http://www.OpenLDAP.org/license.html>.
18e670fd5cSchristos  */
19e670fd5cSchristos /* Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
20e670fd5cSchristos  * All rights reserved.
21e670fd5cSchristos  *
22e670fd5cSchristos  * Redistribution and use in source and binary forms are permitted
23e670fd5cSchristos  * provided that this notice is preserved and that due credit is given
24e670fd5cSchristos  * to the University of Michigan at Ann Arbor.  The name of the
25e670fd5cSchristos  * University may not be used to endorse or promote products derived
26e670fd5cSchristos  * from this software without specific prior written permission.  This
27e670fd5cSchristos  * software is provided ``as is'' without express or implied warranty.
28e670fd5cSchristos  */
29e670fd5cSchristos /* ACKNOWLEDGEMENTS:
30e670fd5cSchristos  * This work was originally developed by Kurt D. Zeilenga for inclusion
31e670fd5cSchristos  * in OpenLDAP Software based, in part, on other client tools.
32e670fd5cSchristos  */
33e670fd5cSchristos 
34e670fd5cSchristos #include <sys/cdefs.h>
35*549b59edSchristos __RCSID("$NetBSD: ldapvc.c,v 1.2 2021/08/14 16:14:49 christos Exp $");
36e670fd5cSchristos 
37e670fd5cSchristos #include "portable.h"
38e670fd5cSchristos 
39e670fd5cSchristos #include <stdio.h>
40e670fd5cSchristos 
41e670fd5cSchristos #include <ac/stdlib.h>
42e670fd5cSchristos 
43e670fd5cSchristos #include <ac/ctype.h>
44e670fd5cSchristos #include <ac/socket.h>
45e670fd5cSchristos #include <ac/string.h>
46e670fd5cSchristos #include <ac/time.h>
47e670fd5cSchristos #include <ac/unistd.h>
48e670fd5cSchristos 
49e670fd5cSchristos #include <ldap.h>
50e670fd5cSchristos #include "lutil.h"
51e670fd5cSchristos #include "lutil_ldap.h"
52e670fd5cSchristos #include "ldap_defaults.h"
53e670fd5cSchristos 
54e670fd5cSchristos #include "common.h"
55e670fd5cSchristos 
56e670fd5cSchristos static int req_authzid = 0;
57e670fd5cSchristos static int req_pp = 0;
58e670fd5cSchristos 
59e670fd5cSchristos #if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
60e670fd5cSchristos #define LDAP_SASL_NONE (~0U)
61e670fd5cSchristos static unsigned vc_sasl = LDAP_SASL_NONE;
62e670fd5cSchristos static char *vc_sasl_realm = NULL;
63e670fd5cSchristos static char *vc_sasl_authcid = NULL;
64e670fd5cSchristos static char *vc_sasl_authzid = NULL;
65e670fd5cSchristos static char *vc_sasl_mech = NULL;
66e670fd5cSchristos static char *vc_sasl_secprops = NULL;
67e670fd5cSchristos #endif
68e670fd5cSchristos static char * dn = NULL;
69e670fd5cSchristos static struct berval cred = {0, NULL};
70e670fd5cSchristos 
71e670fd5cSchristos void
usage(void)72e670fd5cSchristos usage( void )
73e670fd5cSchristos {
74e670fd5cSchristos 	fprintf( stderr, _("Issue LDAP Verify Credentials operation to verify a user's credentials\n\n"));
75e670fd5cSchristos 	fprintf( stderr, _("usage: %s [options] [DN [cred]])\n"), prog);
76e670fd5cSchristos 	fprintf( stderr, _("where:\n"));
77e670fd5cSchristos 	fprintf( stderr, _("    DN\tDistinguished Name\n"));
78e670fd5cSchristos 	fprintf( stderr, _("    cred\tCredentials (prompt if not present)\n"));
79e670fd5cSchristos 	fprintf( stderr, _("options:\n"));
80e670fd5cSchristos 	fprintf( stderr, _("    -a\tRequest AuthzId\n"));
81e670fd5cSchristos 	fprintf( stderr, _("    -b\tRequest Password Policy Information\n"));
82e670fd5cSchristos 	fprintf( stderr, _("    -E sasl=(a[utomatic]|i[nteractive]|q[uiet]>\tSASL mode (defaults to automatic if any other -E option provided, otherwise none))\n"));
83e670fd5cSchristos 	fprintf( stderr, _("    -E mech=<mech>\tSASL mechanism (default "" e.g. Simple)\n"));
84e670fd5cSchristos 	fprintf( stderr, _("    -E realm=<realm>\tSASL Realm (defaults to none)\n"));
85e670fd5cSchristos 	fprintf( stderr, _("    -E authcid=<authcid>\tSASL Authentication Identity (defaults to USER)\n"));
86e670fd5cSchristos 	fprintf( stderr, _("    -E authzid=<authzid>\tSASL Authorization Identity (defaults to none)\n"));
87e670fd5cSchristos 	fprintf( stderr, _("    -E secprops=<secprops>\tSASL Security Properties (defaults to none)\n"));
88e670fd5cSchristos 	tool_common_usage();
89e670fd5cSchristos 	exit( EXIT_FAILURE );
90e670fd5cSchristos }
91e670fd5cSchristos 
92e670fd5cSchristos 
93e670fd5cSchristos const char options[] = "abE:"
94e670fd5cSchristos 	"d:D:e:h:H:InNO:o:p:QR:U:vVw:WxX:y:Y:Z";
95e670fd5cSchristos 
96e670fd5cSchristos int
handle_private_option(int i)97e670fd5cSchristos handle_private_option( int i )
98e670fd5cSchristos {
99e670fd5cSchristos 	switch ( i ) {
100e670fd5cSchristos 		char	*control, *cvalue;
101e670fd5cSchristos 	case 'E': /* vc extension */
102e670fd5cSchristos 		if( protocol == LDAP_VERSION2 ) {
103e670fd5cSchristos 			fprintf( stderr, _("%s: -E incompatible with LDAPv%d\n"),
104e670fd5cSchristos 				prog, protocol );
105e670fd5cSchristos 			exit( EXIT_FAILURE );
106e670fd5cSchristos 		}
107e670fd5cSchristos 
108e670fd5cSchristos 		/* should be extended to support comma separated list of
109e670fd5cSchristos 		 *	[!]key[=value] parameters, e.g.  -E !foo,bar=567
110e670fd5cSchristos 		 */
111e670fd5cSchristos 
112e670fd5cSchristos 		cvalue = NULL;
113e670fd5cSchristos 		if( optarg[0] == '!' ) {
114e670fd5cSchristos 			optarg++;
115e670fd5cSchristos 		}
116e670fd5cSchristos 
117e670fd5cSchristos 		control = optarg;
118e670fd5cSchristos 		if ( (cvalue = strchr( control, '=' )) != NULL ) {
119e670fd5cSchristos 			*cvalue++ = '\0';
120e670fd5cSchristos 		}
121e670fd5cSchristos 
122e670fd5cSchristos 		if (strcasecmp(control, "sasl") == 0) {
123e670fd5cSchristos #if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
124e670fd5cSchristos 			if (vc_sasl != LDAP_SASL_NONE) {
125e670fd5cSchristos 				fprintf(stderr,
126e670fd5cSchristos 				    _("SASL option previously specified\n"));
127e670fd5cSchristos 				exit(EXIT_FAILURE);
128e670fd5cSchristos 			}
129e670fd5cSchristos 			if (cvalue == NULL) {
130e670fd5cSchristos 				fprintf(stderr,
131e670fd5cSchristos 					_("missing mode in SASL option\n"));
132e670fd5cSchristos 				exit(EXIT_FAILURE);
133e670fd5cSchristos 			}
134e670fd5cSchristos 
135e670fd5cSchristos 			switch (*cvalue) {
136e670fd5cSchristos 			case 'a':
137e670fd5cSchristos 			case 'A':
138e670fd5cSchristos 				vc_sasl = LDAP_SASL_AUTOMATIC;
139e670fd5cSchristos 				break;
140e670fd5cSchristos 			case 'i':
141e670fd5cSchristos 			case 'I':
142e670fd5cSchristos 				vc_sasl = LDAP_SASL_INTERACTIVE;
143e670fd5cSchristos 				break;
144e670fd5cSchristos 			case 'q':
145e670fd5cSchristos 			case 'Q':
146e670fd5cSchristos 				vc_sasl = LDAP_SASL_QUIET;
147e670fd5cSchristos 				break;
148e670fd5cSchristos 			default:
149e670fd5cSchristos 				fprintf(stderr,
150e670fd5cSchristos 					_("unknown mode %s in SASL option\n"), cvalue);
151e670fd5cSchristos 				exit(EXIT_FAILURE);
152e670fd5cSchristos 			}
153e670fd5cSchristos #else
154e670fd5cSchristos 			fprintf(stderr,
155e670fd5cSchristos 				_("%s: not compiled with SASL support\n"), prog);
156e670fd5cSchristos 			exit(EXIT_FAILURE);
157e670fd5cSchristos #endif
158e670fd5cSchristos 
159e670fd5cSchristos 		} else if (strcasecmp(control, "mech") == 0) {
160e670fd5cSchristos #if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
161e670fd5cSchristos 			if (vc_sasl_mech) {
162e670fd5cSchristos 				fprintf(stderr,
163e670fd5cSchristos 				    _("SASL mech previously specified\n"));
164e670fd5cSchristos 				exit(EXIT_FAILURE);
165e670fd5cSchristos 			}
166e670fd5cSchristos 			if (cvalue == NULL) {
167e670fd5cSchristos 				fprintf(stderr,
168e670fd5cSchristos 					_("missing mech in SASL option\n"));
169e670fd5cSchristos 				exit(EXIT_FAILURE);
170e670fd5cSchristos 			}
171e670fd5cSchristos 
172e670fd5cSchristos 			vc_sasl_mech = ber_strdup(cvalue);
173e670fd5cSchristos #else
174e670fd5cSchristos #endif
175e670fd5cSchristos 
176e670fd5cSchristos 		} else if (strcasecmp(control, "realm") == 0) {
177e670fd5cSchristos #if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
178e670fd5cSchristos 			if (vc_sasl_realm) {
179e670fd5cSchristos 				fprintf(stderr,
180e670fd5cSchristos 				    _("SASL realm previously specified\n"));
181e670fd5cSchristos 				exit(EXIT_FAILURE);
182e670fd5cSchristos 			}
183e670fd5cSchristos 			if (cvalue == NULL) {
184e670fd5cSchristos 				fprintf(stderr,
185e670fd5cSchristos 					_("missing realm in SASL option\n"));
186e670fd5cSchristos 				exit(EXIT_FAILURE);
187e670fd5cSchristos 			}
188e670fd5cSchristos 
189e670fd5cSchristos 			vc_sasl_realm = ber_strdup(cvalue);
190e670fd5cSchristos #else
191e670fd5cSchristos 			fprintf(stderr,
192e670fd5cSchristos 				_("%s: not compiled with SASL support\n"), prog);
193e670fd5cSchristos 			exit(EXIT_FAILURE);
194e670fd5cSchristos #endif
195e670fd5cSchristos 
196e670fd5cSchristos 		} else if (strcasecmp(control, "authcid") == 0) {
197e670fd5cSchristos #if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
198e670fd5cSchristos 			if (vc_sasl_authcid) {
199e670fd5cSchristos 				fprintf(stderr,
200e670fd5cSchristos 				    _("SASL authcid previously specified\n"));
201e670fd5cSchristos 				exit(EXIT_FAILURE);
202e670fd5cSchristos 			}
203e670fd5cSchristos 			if (cvalue == NULL) {
204e670fd5cSchristos 				fprintf(stderr,
205e670fd5cSchristos 					_("missing authcid in SASL option\n"));
206e670fd5cSchristos 				exit(EXIT_FAILURE);
207e670fd5cSchristos 			}
208e670fd5cSchristos 
209e670fd5cSchristos 			vc_sasl_authcid = ber_strdup(cvalue);
210e670fd5cSchristos #else
211e670fd5cSchristos 			fprintf(stderr,
212e670fd5cSchristos 				_("%s: not compiled with SASL support\n"), prog);
213e670fd5cSchristos 			exit(EXIT_FAILURE);
214e670fd5cSchristos #endif
215e670fd5cSchristos 
216e670fd5cSchristos 		} else if (strcasecmp(control, "authzid") == 0) {
217e670fd5cSchristos #if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
218e670fd5cSchristos 			if (vc_sasl_authzid) {
219e670fd5cSchristos 				fprintf(stderr,
220e670fd5cSchristos 				    _("SASL authzid previously specified\n"));
221e670fd5cSchristos 				exit(EXIT_FAILURE);
222e670fd5cSchristos 			}
223e670fd5cSchristos 			if (cvalue == NULL) {
224e670fd5cSchristos 				fprintf(stderr,
225e670fd5cSchristos 					_("missing authzid in SASL option\n"));
226e670fd5cSchristos 				exit(EXIT_FAILURE);
227e670fd5cSchristos 			}
228e670fd5cSchristos 
229e670fd5cSchristos 			vc_sasl_authzid = ber_strdup(cvalue);
230e670fd5cSchristos #else
231e670fd5cSchristos 			fprintf(stderr,
232e670fd5cSchristos 				_("%s: not compiled with SASL support\n"), prog);
233e670fd5cSchristos 			exit(EXIT_FAILURE);
234e670fd5cSchristos #endif
235e670fd5cSchristos 
236e670fd5cSchristos 		} else if (strcasecmp(control, "secprops") == 0) {
237e670fd5cSchristos #if defined(LDAP_API_FEATURES_VERIFY_CREDENTIALS_INTERACTIVE) && defined(HAVE_CYRUS_SASL)
238e670fd5cSchristos 			if (vc_sasl_secprops) {
239e670fd5cSchristos 				fprintf(stderr,
240e670fd5cSchristos 				    _("SASL secprops previously specified\n"));
241e670fd5cSchristos 				exit(EXIT_FAILURE);
242e670fd5cSchristos 			}
243e670fd5cSchristos 			if (cvalue == NULL) {
244e670fd5cSchristos 				fprintf(stderr,
245e670fd5cSchristos 					_("missing secprops in SASL option\n"));
246e670fd5cSchristos 				exit(EXIT_FAILURE);
247e670fd5cSchristos 			}
248e670fd5cSchristos 
249e670fd5cSchristos 			vc_sasl_secprops = ber_strdup(cvalue);
250e670fd5cSchristos #else
251e670fd5cSchristos 			fprintf(stderr,
252e670fd5cSchristos 				_("%s: not compiled with SASL support\n"), prog);
253e670fd5cSchristos 			exit(EXIT_FAILURE);
254e670fd5cSchristos #endif
255e670fd5cSchristos 
256e670fd5cSchristos 		} else {
257e670fd5cSchristos 		    fprintf( stderr, _("Invalid Verify Credentials extension name: %s\n"), control );
258e670fd5cSchristos 		    usage();
259e670fd5cSchristos 		}
260e670fd5cSchristos 		break;
261e670fd5cSchristos 
262e670fd5cSchristos 	case 'a':  /* request authzid */
263e670fd5cSchristos 		req_authzid++;
264e670fd5cSchristos 		break;
265e670fd5cSchristos 
266e670fd5cSchristos 	case 'b':  /* request authzid */
267e670fd5cSchristos 		req_pp++;
268e670fd5cSchristos 		break;
269e670fd5cSchristos 
270e670fd5cSchristos 	default:
271e670fd5cSchristos 		return 0;
272e670fd5cSchristos 	}
273e670fd5cSchristos 	return 1;
274e670fd5cSchristos }
275e670fd5cSchristos 
276e670fd5cSchristos 
277e670fd5cSchristos int
main(int argc,char * argv[])278e670fd5cSchristos main( int argc, char *argv[] )
279e670fd5cSchristos {
280e670fd5cSchristos 	int		rc;
281e670fd5cSchristos 	LDAP		*ld = NULL;
282e670fd5cSchristos 	char		*matcheddn = NULL, *text = NULL, **refs = NULL;
283e670fd5cSchristos 	int rcode;
284e670fd5cSchristos 	char * diag = NULL;
285e670fd5cSchristos 	struct berval	*scookie = NULL;
286e670fd5cSchristos 	struct berval	*scred = NULL;
287e670fd5cSchristos 	int		id, code = 0;
288e670fd5cSchristos 	LDAPMessage	*res;
289e670fd5cSchristos 	LDAPControl	**ctrls = NULL;
290e670fd5cSchristos 	LDAPControl	**vcctrls = NULL;
291e670fd5cSchristos 	int nvcctrls = 0;
292e670fd5cSchristos 
293e670fd5cSchristos 	tool_init( TOOL_VC );
294e670fd5cSchristos 	prog = lutil_progname( "ldapvc", argc, argv );
295e670fd5cSchristos 
296e670fd5cSchristos 	/* LDAPv3 only */
297e670fd5cSchristos 	protocol = LDAP_VERSION3;
298e670fd5cSchristos 
299e670fd5cSchristos 	tool_args( argc, argv );
300e670fd5cSchristos 
301e670fd5cSchristos 	if (argc - optind > 0) {
302e670fd5cSchristos 		dn = argv[optind++];
303e670fd5cSchristos 	}
304e670fd5cSchristos 	if (argc - optind > 0) {
305e670fd5cSchristos 		cred.bv_val = strdup(argv[optind++]);
306e670fd5cSchristos 		cred.bv_len = strlen(cred.bv_val);
307e670fd5cSchristos 	}
308e670fd5cSchristos 	if (argc - optind > 0) {
309e670fd5cSchristos 		usage();
310e670fd5cSchristos 	}
311e670fd5cSchristos 	if (dn
312e670fd5cSchristos #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS_INTERACTIVE
313e670fd5cSchristos            && !vc_sasl_mech
314e670fd5cSchristos #endif
315e670fd5cSchristos            && !cred.bv_val)
316e670fd5cSchristos 	{
317e670fd5cSchristos 		cred.bv_val = strdup(getpassphrase(_("User's password: ")));
318e670fd5cSchristos 	    cred.bv_len = strlen(cred.bv_val);
319e670fd5cSchristos 	}
320e670fd5cSchristos 
321e670fd5cSchristos #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS_INTERACTIVE
322e670fd5cSchristos     if (vc_sasl_mech && (vc_sasl == LDAP_SASL_NONE)) {
323e670fd5cSchristos 		vc_sasl = LDAP_SASL_AUTOMATIC;
324e670fd5cSchristos 	}
325e670fd5cSchristos #endif
326e670fd5cSchristos 
327e670fd5cSchristos 	ld = tool_conn_setup( 0, 0 );
328e670fd5cSchristos 
329e670fd5cSchristos 	tool_bind( ld );
330e670fd5cSchristos 
331e670fd5cSchristos 	if ( dont ) {
332e670fd5cSchristos 		rc = LDAP_SUCCESS;
333e670fd5cSchristos 		goto skip;
334e670fd5cSchristos 	}
335e670fd5cSchristos 
336e670fd5cSchristos 	tool_server_controls( ld, NULL, 0 );
337e670fd5cSchristos 
338e670fd5cSchristos     if (req_authzid) {
339e670fd5cSchristos 		vcctrls = (LDAPControl **) malloc(3*sizeof(LDAPControl *));
340e670fd5cSchristos 		vcctrls[nvcctrls] = (LDAPControl *) malloc(sizeof(LDAPControl));
341e670fd5cSchristos 		vcctrls[nvcctrls]->ldctl_oid = ldap_strdup(LDAP_CONTROL_AUTHZID_REQUEST);
342e670fd5cSchristos 		vcctrls[nvcctrls]->ldctl_iscritical = 0;
343e670fd5cSchristos 		vcctrls[nvcctrls]->ldctl_value.bv_val = NULL;
344e670fd5cSchristos 		vcctrls[nvcctrls]->ldctl_value.bv_len = 0;
345e670fd5cSchristos 		vcctrls[++nvcctrls] = NULL;
346e670fd5cSchristos     }
347e670fd5cSchristos 
348e670fd5cSchristos     if (req_pp) {
349e670fd5cSchristos 		if (!vcctrls) vcctrls = (LDAPControl **) malloc(3*sizeof(LDAPControl *));
350e670fd5cSchristos 		vcctrls[nvcctrls] = (LDAPControl *) malloc(sizeof(LDAPControl));
351e670fd5cSchristos 		vcctrls[nvcctrls]->ldctl_oid = ldap_strdup(LDAP_CONTROL_PASSWORDPOLICYREQUEST);
352e670fd5cSchristos 		vcctrls[nvcctrls]->ldctl_iscritical = 0;
353e670fd5cSchristos 		vcctrls[nvcctrls]->ldctl_value.bv_val = NULL;
354e670fd5cSchristos 		vcctrls[nvcctrls]->ldctl_value.bv_len = 0;
355e670fd5cSchristos 		vcctrls[++nvcctrls] = NULL;
356e670fd5cSchristos     }
357e670fd5cSchristos 
358e670fd5cSchristos #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS_INTERACTIVE
359e670fd5cSchristos #ifdef HAVE_CYRUS_SASL
360e670fd5cSchristos     if (vc_sasl_mech) {
361e670fd5cSchristos 		int msgid;
362e670fd5cSchristos 		void * defaults;
363e670fd5cSchristos 		void * context = NULL;
364e670fd5cSchristos 		const char *rmech = NULL;
365e670fd5cSchristos 
366e670fd5cSchristos 		defaults = lutil_sasl_defaults(ld,
367e670fd5cSchristos 			vc_sasl_mech,
368e670fd5cSchristos 			vc_sasl_realm,
369e670fd5cSchristos 			vc_sasl_authcid,
370e670fd5cSchristos 			cred.bv_val,
371e670fd5cSchristos 			sasl_authz_id);
372e670fd5cSchristos 
373e670fd5cSchristos 		do {
374e670fd5cSchristos 			rc = ldap_verify_credentials_interactive(ld, dn, vc_sasl_mech,
375e670fd5cSchristos 				vcctrls, NULL, NULL,
376e670fd5cSchristos 				vc_sasl, lutil_sasl_interact, defaults, context,
377e670fd5cSchristos 				res, &rmech, &msgid);
378e670fd5cSchristos 
379e670fd5cSchristos 			if (rc != LDAP_SASL_BIND_IN_PROGRESS) break;
380e670fd5cSchristos 
381e670fd5cSchristos 			ldap_msgfree(res);
382e670fd5cSchristos 
383e670fd5cSchristos 			if (ldap_result(ld, msgid, LDAP_MSG_ALL, NULL, &res) == -1 || !res) {
384e670fd5cSchristos 				ldap_get_option(ld, LDAP_OPT_RESULT_CODE, (void*) &rc);
385e670fd5cSchristos 				ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*) &text);
386e670fd5cSchristos 				tool_perror( "ldap_verify_credentials_interactive", rc, NULL, NULL, text, NULL);
387e670fd5cSchristos 				ldap_memfree(text);
388e670fd5cSchristos 				tool_exit(ld, rc);
389e670fd5cSchristos 			}
390e670fd5cSchristos 		} while (rc == LDAP_SASL_BIND_IN_PROGRESS);
391e670fd5cSchristos 
392e670fd5cSchristos 	    lutil_sasl_freedefs(defaults);
393e670fd5cSchristos 
394e670fd5cSchristos 	    if( rc != LDAP_SUCCESS ) {
395e670fd5cSchristos 			ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*) &text);
396e670fd5cSchristos 		    tool_perror( "ldap_verify_credentials", rc, NULL, NULL, text, NULL );
397e670fd5cSchristos 		    rc = EXIT_FAILURE;
398e670fd5cSchristos 		    goto skip;
399e670fd5cSchristos 	    }
400e670fd5cSchristos 
401e670fd5cSchristos 	} else
402e670fd5cSchristos #endif
403e670fd5cSchristos #endif
404e670fd5cSchristos     {
405e670fd5cSchristos 	    rc = ldap_verify_credentials( ld,
406e670fd5cSchristos 		    NULL,
407e670fd5cSchristos 		    dn, NULL, cred.bv_val ? &cred: NULL, vcctrls,
408e670fd5cSchristos 		    NULL, NULL, &id );
409e670fd5cSchristos 
410e670fd5cSchristos 	    if( rc != LDAP_SUCCESS ) {
411e670fd5cSchristos 			ldap_get_option(ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*) &text);
412e670fd5cSchristos 		    tool_perror( "ldap_verify_credentials", rc, NULL, NULL, text, NULL );
413e670fd5cSchristos 		    rc = EXIT_FAILURE;
414e670fd5cSchristos 		    goto skip;
415e670fd5cSchristos 	    }
416e670fd5cSchristos 
417e670fd5cSchristos 	    for ( ; ; ) {
418e670fd5cSchristos 		    struct timeval	tv;
419e670fd5cSchristos 
420e670fd5cSchristos 		    if ( tool_check_abandon( ld, id ) ) {
421e670fd5cSchristos 			    tool_exit( ld, LDAP_CANCELLED );
422e670fd5cSchristos 		    }
423e670fd5cSchristos 
424e670fd5cSchristos 		    tv.tv_sec = 0;
425e670fd5cSchristos 		    tv.tv_usec = 100000;
426e670fd5cSchristos 
427e670fd5cSchristos 		    rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, &tv, &res );
428e670fd5cSchristos 		    if ( rc < 0 ) {
429e670fd5cSchristos 			    tool_perror( "ldap_result", rc, NULL, NULL, NULL, NULL );
430e670fd5cSchristos 			    tool_exit( ld, rc );
431e670fd5cSchristos 		    }
432e670fd5cSchristos 
433e670fd5cSchristos 		    if ( rc != 0 ) {
434e670fd5cSchristos 			    break;
435e670fd5cSchristos 		    }
436e670fd5cSchristos 	    }
437e670fd5cSchristos 	}
438e670fd5cSchristos 
439e670fd5cSchristos 	ldap_controls_free(vcctrls);
440e670fd5cSchristos 	vcctrls = NULL;
441e670fd5cSchristos 
442e670fd5cSchristos 	rc = ldap_parse_result( ld, res,
443e670fd5cSchristos 		&code, &matcheddn, &text, &refs, &ctrls, 0 );
444e670fd5cSchristos 
445e670fd5cSchristos 	if (rc == LDAP_SUCCESS) rc = code;
446e670fd5cSchristos 
447e670fd5cSchristos 	if (rc != LDAP_SUCCESS) {
448e670fd5cSchristos 		tool_perror( "ldap_parse_result", rc, NULL, matcheddn, text, refs );
449e670fd5cSchristos 		rc = EXIT_FAILURE;
450e670fd5cSchristos 		goto skip;
451e670fd5cSchristos 	}
452e670fd5cSchristos 
453e670fd5cSchristos 	rc = ldap_parse_verify_credentials( ld, res, &rcode, &diag, &scookie, &scred, &vcctrls );
454e670fd5cSchristos 	ldap_msgfree(res);
455e670fd5cSchristos 
456e670fd5cSchristos 	if (rc != LDAP_SUCCESS) {
457e670fd5cSchristos 		tool_perror( "ldap_parse_verify_credentials", rc, NULL, NULL, NULL, NULL );
458e670fd5cSchristos 		rc = EXIT_FAILURE;
459e670fd5cSchristos 		goto skip;
460e670fd5cSchristos 	}
461e670fd5cSchristos 
462e670fd5cSchristos 	if (rcode != LDAP_SUCCESS) {
463e670fd5cSchristos 		printf(_("Failed: %s (%d)\n"), ldap_err2string(rcode), rcode);
464e670fd5cSchristos 	}
465e670fd5cSchristos 
466e670fd5cSchristos 	if (diag && *diag) {
467e670fd5cSchristos 	    printf(_("Diagnostic: %s\n"), diag);
468e670fd5cSchristos 	}
469e670fd5cSchristos 
470e670fd5cSchristos 	if (vcctrls) {
471e670fd5cSchristos 		tool_print_ctrls( ld, vcctrls );
472e670fd5cSchristos 	}
473e670fd5cSchristos 
474e670fd5cSchristos skip:
475e670fd5cSchristos 	if ( verbose || code != LDAP_SUCCESS ||
476e670fd5cSchristos 		( matcheddn && *matcheddn ) || ( text && *text ) || refs || ctrls )
477e670fd5cSchristos 	{
478e670fd5cSchristos 		printf( _("Result: %s (%d)\n"), ldap_err2string( code ), code );
479e670fd5cSchristos 
480e670fd5cSchristos 		if( text && *text ) {
481e670fd5cSchristos 			printf( _("Additional info: %s\n"), text );
482e670fd5cSchristos 		}
483e670fd5cSchristos 
484e670fd5cSchristos 		if( matcheddn && *matcheddn ) {
485e670fd5cSchristos 			printf( _("Matched DN: %s\n"), matcheddn );
486e670fd5cSchristos 		}
487e670fd5cSchristos 
488e670fd5cSchristos 		if( refs ) {
489e670fd5cSchristos 			int i;
490e670fd5cSchristos 			for( i=0; refs[i]; i++ ) {
491e670fd5cSchristos 				printf(_("Referral: %s\n"), refs[i] );
492e670fd5cSchristos 			}
493e670fd5cSchristos 		}
494e670fd5cSchristos 
495e670fd5cSchristos 		if (ctrls) {
496e670fd5cSchristos 			tool_print_ctrls( ld, ctrls );
497e670fd5cSchristos 			ldap_controls_free( ctrls );
498e670fd5cSchristos 		}
499e670fd5cSchristos 	}
500e670fd5cSchristos 
501e670fd5cSchristos 	ber_memfree( text );
502e670fd5cSchristos 	ber_memfree( matcheddn );
503e670fd5cSchristos 	ber_memvfree( (void **) refs );
504e670fd5cSchristos 	ber_bvfree( scookie );
505e670fd5cSchristos 	ber_bvfree( scred );
506e670fd5cSchristos 	ber_memfree( diag );
507e670fd5cSchristos 	free( cred.bv_val );
508e670fd5cSchristos 
509e670fd5cSchristos 	/* disconnect from server */
510e670fd5cSchristos 	tool_exit( ld, code == LDAP_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE );
511e670fd5cSchristos }
512