]> git.sur5r.net Git - openldap/blob - clients/tools/ldappasswd.c
32c8650cd3641f6d3c5183e4c027f24f22952f89
[openldap] / clients / tools / ldappasswd.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2000 The OpenLDAP Foundation, All Rights Reserved.
4  * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
5  */
6
7 #include "portable.h"
8
9 #include <stdio.h>
10
11 #include <ac/stdlib.h>
12
13 #include <ac/ctype.h>
14 #include <ac/signal.h>
15 #include <ac/socket.h>
16 #include <ac/string.h>
17 #include <ac/time.h>
18 #include <ac/unistd.h>
19
20 #include <ldap.h>
21
22 #include "lutil_ldap.h"
23 #include "ldap_defaults.h"
24
25 static int      verbose = 0;
26
27 static void
28 usage(const char *s)
29 {
30         fprintf(stderr,
31 "Change password of an LDAP user\n\n"
32 "usage: %s [options] user\n"
33 "  user: the identity of the user, normally a DN\n"
34 "Password change options:\n"
35 "  -a secret  old password\n"
36 "  -A         prompt for old password\n"
37 "  -s secret  new password\n"
38 "  -S         prompt for new password\n"
39
40 "Common options:\n"
41 "  -d level   set LDAP debugging level to `level'\n"
42 "  -D binddn  bind DN\n"
43 "  -f file    read operations from `file'\n"
44 "  -h host    LDAP server\n"
45 "  -I         use SASL Interactive mode\n"
46 "  -n         show what would be done but don't actually search\n"
47 "  -O props   SASL security properties\n"
48 "  -p port    port on LDAP server\n"
49 "  -Q         use SASL Quiet mode\n"
50 "  -R realm   SASL realm\n"
51 "  -U user    SASL authentication identity (username)\n"
52 "  -v         run in verbose mode (diagnostics to standard output)\n"
53 "  -w passwd  bind passwd (for simple authentication)\n"
54 "  -W         prompt for bind passwd\n"
55 "  -x         Simple authentication\n"
56 "  -X id      SASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
57 "  -Y mech    SASL mechanism\n"
58 "  -Z         Start TLS request (-ZZ to require successful response)\n"
59                 , s );
60
61         exit( EXIT_FAILURE );
62 }
63
64 int
65 main( int argc, char *argv[] )
66 {
67         int rc;
68         char    *prog = NULL;
69         char    *ldaphost = NULL;
70
71         char    *dn = NULL;
72         char    *binddn = NULL;
73
74         struct berval passwd = { 0, NULL };
75         char    *newpw = NULL;
76         char    *oldpw = NULL;
77
78         int             want_bindpw = 0;
79         int             want_newpw = 0;
80         int             want_oldpw = 0;
81
82         int             not = 0;
83         int             i;
84         int             ldapport = 0;
85         int             debug = 0;
86         int             version = -1;
87         int             authmethod = -1;
88         int             manageDSAit = 0;
89 #ifdef HAVE_CYRUS_SASL
90         unsigned        sasl_flags = LDAP_SASL_AUTOMATIC;
91         char            *sasl_realm = NULL;
92         char            *sasl_authc_id = NULL;
93         char            *sasl_authz_id = NULL;
94         char            *sasl_mech = NULL;
95         char            *sasl_secprops = NULL;
96 #endif
97         int             use_tls = 0;
98         int             referrals = 0;
99         LDAP           *ld;
100         struct berval *bv = NULL;
101
102         int id, code;
103         LDAPMessage *res;
104         char *matcheddn = NULL, *text = NULL, **refs = NULL;
105         char    *retoid = NULL;
106         struct berval *retdata = NULL;
107
108     prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : ++prog;
109
110         if (argc == 1)
111                 usage (argv[0]);
112
113         while( (i = getopt( argc, argv,
114                 "Aa:Ss:" "Cd:D:h:InO:p:QRU:vw:WxX:Y:Z" )) != EOF )
115         {
116                 switch (i) {
117                 /* Password Options */
118                 case 'A':       /* prompt for old password */
119                         want_oldpw++;
120                         break;
121
122                 case 'a':       /* old password (secret) */
123                         oldpw = strdup (optarg);
124
125                         {
126                                 char* p;
127
128                                 for( p = optarg; *p == '\0'; p++ ) {
129                                         *p = '\0';
130                                 }
131                         }
132                         break;
133
134                 case 'S':       /* prompt for user password */
135                         want_newpw++;
136                         break;
137
138                 case 's':       /* new password (secret) */
139                         newpw = strdup (optarg);
140                         {
141                                 char* p;
142
143                                 for( p = optarg; *p == '\0'; p++ ) {
144                                         *p = '\0';
145                                 }
146                         }
147                         break;
148
149         /* Common Options (including options we don't use) */
150         case 'C':
151                 referrals++;
152                 break;
153         case 'd':
154             debug |= atoi( optarg );
155             break;
156         case 'D':       /* bind DN */
157                 if( binddn != NULL ) {
158                         fprintf( stderr, "%s: -D previously specified\n" );
159                         return EXIT_FAILURE;
160                 }
161             binddn = strdup( optarg );
162             break;
163         case 'h':       /* ldap host */
164                 if( ldaphost != NULL ) {
165                         fprintf( stderr, "%s: -h previously specified\n" );
166                         return EXIT_FAILURE;
167                 }
168             ldaphost = strdup( optarg );
169             break;
170         case 'I':
171 #ifdef HAVE_CYRUS_SASL
172                 if( version == LDAP_VERSION2 ) {
173                         fprintf( stderr, "%s: -I incompatible with version %d\n",
174                                 prog, version );
175                         return EXIT_FAILURE;
176                 }
177                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
178                         fprintf( stderr, "%s: incompatible previous "
179                                 "authentication choice\n",
180                                 prog );
181                         return EXIT_FAILURE;
182                 }
183                 authmethod = LDAP_AUTH_SASL;
184                 version = LDAP_VERSION3;
185                 sasl_flags = LDAP_SASL_INTERACTIVE;
186                 break;
187 #else
188                 fprintf( stderr, "%s: was not compiled with SASL support\n",
189                         prog );
190                 return( EXIT_FAILURE );
191 #endif
192         case 'k':       /* kerberos bind */
193 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
194                 if( version > LDAP_VERSION2 ) {
195                         fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
196                                 prog, version );
197                         return EXIT_FAILURE;
198                 }
199
200                 if( authmethod != -1 ) {
201                         fprintf( stderr, "%s: -k incompatible with previous "
202                                 "authentication choice\n", prog );
203                         return EXIT_FAILURE;
204                 }
205                         
206                 authmethod = LDAP_AUTH_KRBV4;
207 #else
208                 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
209                 return EXIT_FAILURE;
210 #endif
211             break;
212         case 'K':       /* kerberos bind, part one only */
213 #ifdef LDAP_API_FEATURE_X_OPENLDAP_V2_KBIND
214                 if( version > LDAP_VERSION2 ) {
215                         fprintf( stderr, "%s: -k incompatible with LDAPv%d\n",
216                                 prog, version );
217                         return EXIT_FAILURE;
218                 }
219                 if( authmethod != -1 ) {
220                         fprintf( stderr, "%s: incompatible with previous "
221                                 "authentication choice\n", prog );
222                         return EXIT_FAILURE;
223                 }
224
225                 authmethod = LDAP_AUTH_KRBV41;
226 #else
227                 fprintf( stderr, "%s: not compiled with Kerberos support\n", prog );
228                 return( EXIT_FAILURE );
229 #endif
230             break;
231         case 'M':
232                 /* enable Manage DSA IT */
233                 if( version == LDAP_VERSION2 ) {
234                         fprintf( stderr, "%s: -M incompatible with LDAPv%d\n",
235                                 prog, version );
236                         return EXIT_FAILURE;
237                 }
238                 manageDSAit++;
239                 version = LDAP_VERSION3;
240                 break;
241         case 'n':       /* print deletes, don't actually do them */
242             ++not;
243             break;
244         case 'O':
245 #ifdef HAVE_CYRUS_SASL
246                 if( sasl_secprops != NULL ) {
247                         fprintf( stderr, "%s: -O previously specified\n" );
248                         return EXIT_FAILURE;
249                 }
250                 if( version == LDAP_VERSION2 ) {
251                         fprintf( stderr, "%s: -O incompatible with LDAPv%d\n",
252                                 prog, version );
253                         return EXIT_FAILURE;
254                 }
255                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
256                         fprintf( stderr, "%s: incompatible previous "
257                                 "authentication choice\n", prog );
258                         return EXIT_FAILURE;
259                 }
260                 authmethod = LDAP_AUTH_SASL;
261                 version = LDAP_VERSION3;
262                 sasl_secprops = strdup( optarg );
263 #else
264                 fprintf( stderr, "%s: not compiled with SASL support\n",
265                         prog );
266                 return( EXIT_FAILURE );
267 #endif
268                 break;
269         case 'p':
270                 if( ldapport ) {
271                         fprintf( stderr, "%s: -p previously specified\n" );
272                         return EXIT_FAILURE;
273                 }
274             ldapport = atoi( optarg );
275             break;
276         case 'P':
277                 switch( atoi(optarg) ) {
278                 case 2:
279                         if( version == LDAP_VERSION3 ) {
280                                 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
281                                         prog, version );
282                                 return EXIT_FAILURE;
283                         }
284                         version = LDAP_VERSION2;
285                         break;
286                 case 3:
287                         if( version == LDAP_VERSION2 ) {
288                                 fprintf( stderr, "%s: -P 2 incompatible with version %d\n",
289                                         prog, version );
290                                 return EXIT_FAILURE;
291                         }
292                         version = LDAP_VERSION3;
293                         break;
294                 default:
295                         fprintf( stderr, "%s: protocol version should be 2 or 3\n",
296                                 prog );
297                         usage( prog );
298                         return( EXIT_FAILURE );
299                 } break;
300         case 'Q':
301 #ifdef HAVE_CYRUS_SASL
302                 if( version == LDAP_VERSION2 ) {
303                         fprintf( stderr, "%s: -Q incompatible with version %d\n",
304                                 prog, version );
305                         return EXIT_FAILURE;
306                 }
307                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
308                         fprintf( stderr, "%s: incompatible previous "
309                                 "authentication choice\n",
310                                 prog );
311                         return EXIT_FAILURE;
312                 }
313                 authmethod = LDAP_AUTH_SASL;
314                 version = LDAP_VERSION3;
315                 sasl_flags = LDAP_SASL_QUIET;
316                 break;
317 #else
318                 fprintf( stderr, "%s: not compiled with SASL support\n",
319                         prog );
320                 return( EXIT_FAILURE );
321 #endif
322         case 'R':
323 #ifdef HAVE_CYRUS_SASL
324                 if( sasl_realm != NULL ) {
325                         fprintf( stderr, "%s: -R previously specified\n" );
326                         return EXIT_FAILURE;
327                 }
328                 if( version == LDAP_VERSION2 ) {
329                         fprintf( stderr, "%s: -R incompatible with version %d\n",
330                                 prog, version );
331                         return EXIT_FAILURE;
332                 }
333                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
334                         fprintf( stderr, "%s: incompatible previous "
335                                 "authentication choice\n",
336                                 prog );
337                         return EXIT_FAILURE;
338                 }
339                 authmethod = LDAP_AUTH_SASL;
340                 version = LDAP_VERSION3;
341                 sasl_realm = strdup( optarg );
342 #else
343                 fprintf( stderr, "%s: not compiled with SASL support\n",
344                         prog );
345                 return( EXIT_FAILURE );
346 #endif
347                 break;
348         case 'U':
349 #ifdef HAVE_CYRUS_SASL
350                 if( sasl_authc_id != NULL ) {
351                         fprintf( stderr, "%s: -U previously specified\n" );
352                         return EXIT_FAILURE;
353                 }
354                 if( version == LDAP_VERSION2 ) {
355                         fprintf( stderr, "%s: -U incompatible with version %d\n",
356                                 prog, version );
357                         return EXIT_FAILURE;
358                 }
359                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
360                         fprintf( stderr, "%s: incompatible previous "
361                                 "authentication choice\n",
362                                 prog );
363                         return EXIT_FAILURE;
364                 }
365                 authmethod = LDAP_AUTH_SASL;
366                 version = LDAP_VERSION3;
367                 sasl_authc_id = strdup( optarg );
368 #else
369                 fprintf( stderr, "%s: not compiled with SASL support\n",
370                         prog );
371                 return( EXIT_FAILURE );
372 #endif
373                 break;
374         case 'v':       /* verbose mode */
375             verbose++;
376             break;
377         case 'w':       /* password */
378             passwd.bv_val = strdup( optarg );
379                 {
380                         char* p;
381
382                         for( p = optarg; *p == '\0'; p++ ) {
383                                 *p = '\0';
384                         }
385                 }
386                 passwd.bv_len = strlen( passwd.bv_val );
387             break;
388         case 'W':
389                 want_bindpw++;
390                 break;
391         case 'Y':
392 #ifdef HAVE_CYRUS_SASL
393                 if( sasl_mech != NULL ) {
394                         fprintf( stderr, "%s: -Y previously specified\n" );
395                         return EXIT_FAILURE;
396                 }
397                 if( version == LDAP_VERSION2 ) {
398                         fprintf( stderr, "%s: -Y incompatible with version %d\n",
399                                 prog, version );
400                         return EXIT_FAILURE;
401                 }
402                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
403                         fprintf( stderr, "%s: incompatible with authentication choice\n", prog );
404                         return EXIT_FAILURE;
405                 }
406                 authmethod = LDAP_AUTH_SASL;
407                 version = LDAP_VERSION3;
408                 sasl_mech = strdup( optarg );
409 #else
410                 fprintf( stderr, "%s: not compiled with SASL support\n",
411                         prog );
412                 return( EXIT_FAILURE );
413 #endif
414                 break;
415         case 'x':
416                 if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
417                         fprintf( stderr, "%s: incompatible with previous "
418                                 "authentication choice\n", prog );
419                         return EXIT_FAILURE;
420                 }
421                 authmethod = LDAP_AUTH_SIMPLE;
422                 break;
423         case 'X':
424 #ifdef HAVE_CYRUS_SASL
425                 if( sasl_authz_id != NULL ) {
426                         fprintf( stderr, "%s: -X previously specified\n" );
427                         return EXIT_FAILURE;
428                 }
429                 if( version == LDAP_VERSION2 ) {
430                         fprintf( stderr, "%s: -X incompatible with LDAPv%d\n",
431                                 prog, version );
432                         return EXIT_FAILURE;
433                 }
434                 if( authmethod != -1 && authmethod != LDAP_AUTH_SASL ) {
435                         fprintf( stderr, "%s: -X incompatible with "
436                                 "authentication choice\n", prog );
437                         return EXIT_FAILURE;
438                 }
439                 authmethod = LDAP_AUTH_SASL;
440                 version = LDAP_VERSION3;
441                 sasl_authz_id = strdup( optarg );
442 #else
443                 fprintf( stderr, "%s: not compiled with SASL support\n",
444                         prog );
445                 return( EXIT_FAILURE );
446 #endif
447                 break;
448         case 'Z':
449 #ifdef HAVE_TLS
450                 if( version == LDAP_VERSION2 ) {
451                         fprintf( stderr, "%s: -Z incompatible with version %d\n",
452                                 prog, version );
453                         return EXIT_FAILURE;
454                 }
455                 version = LDAP_VERSION3;
456                 use_tls++;
457 #else
458                 fprintf( stderr, "%s: not compiled with TLS support\n",
459                         prog );
460                 return( EXIT_FAILURE );
461 #endif
462                 break;
463
464
465                 default:
466                         fprintf( stderr, "%s: unrecongized option -%c\n",
467                                 prog, optopt );
468                         usage (argv[0]);
469                 }
470         }
471
472         if( argc - optind != 1 ) {
473                 usage( argv[0] );
474         } 
475
476         if (authmethod == -1) {
477 #ifdef HAVE_CYRUS_SASL
478                 authmethod = LDAP_AUTH_SASL;
479 #else
480                 authmethod = LDAP_AUTH_SIMPLE;
481 #endif
482         }
483
484         dn = strdup( argv[optind] );
485
486         if( want_oldpw && oldpw == NULL ) {
487                 /* prompt for old password */
488                 char *ckoldpw;
489                 newpw = strdup(getpassphrase("Old password: "));
490                 ckoldpw = getpassphrase("Re-enter old password: ");
491
492                 if( newpw== NULL || ckoldpw == NULL ||
493                         strncmp( oldpw, ckoldpw, strlen(oldpw) ))
494                 {
495                         fprintf( stderr, "passwords do not match\n" );
496                         return EXIT_FAILURE;
497                 }
498         }
499
500         if( want_newpw && newpw == NULL ) {
501                 /* prompt for new password */
502                 char *cknewpw;
503                 newpw = strdup(getpassphrase("New password: "));
504                 cknewpw = getpassphrase("Re-enter new password: ");
505
506                 if( newpw== NULL || cknewpw == NULL ||
507                         strncmp( newpw, cknewpw, strlen(newpw) ))
508                 {
509                         fprintf( stderr, "passwords do not match\n" );
510                         return EXIT_FAILURE;
511                 }
512         }
513
514         if( binddn == NULL && dn != NULL ) {
515                 binddn = dn;
516                 dn = NULL;
517
518                 if( passwd.bv_val == NULL ) {
519                         passwd.bv_val = oldpw;
520                         passwd.bv_len = oldpw == NULL ? 0 : strlen( oldpw );
521                 }
522         }
523
524         if (want_bindpw && passwd.bv_val == NULL ) {
525                 /* handle bind password */
526                 fprintf( stderr, "Bind DN: %s\n", binddn );
527                 passwd.bv_val = strdup( getpassphrase("Enter bind password: "));
528                 passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
529         }
530
531         if ( debug ) {
532                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
533                         fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
534                 }
535                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
536                         fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
537                 }
538         }
539
540 #ifdef SIGPIPE
541         (void) SIGNAL( SIGPIPE, SIG_IGN );
542 #endif
543
544         /* connect to server */
545         if ((ld = ldap_init( ldaphost, ldapport )) == NULL) {
546                 perror("ldap_init");
547                 return EXIT_FAILURE;
548         }
549
550         /* referrals */
551         if (ldap_set_option( ld, LDAP_OPT_REFERRALS,
552                 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
553         {
554                 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
555                         referrals ? "on" : "off" );
556                 return EXIT_FAILURE;
557         }
558
559         /* LDAPv3 only */
560         version = 3;
561         rc = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
562
563         if(rc != LDAP_OPT_SUCCESS ) {
564                 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
565                 return EXIT_FAILURE;
566         }
567
568         if ( use_tls && ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
569                 if ( use_tls > 1 ) {
570                         ldap_perror( ld, "ldap_start_tls" );
571                         return( EXIT_FAILURE );
572                 }
573                 fprintf( stderr, "WARNING: could not start TLS\n" );
574         }
575
576         if ( authmethod == LDAP_AUTH_SASL ) {
577 #ifdef HAVE_CYRUS_SASL
578                 void *defaults;
579
580                 if( sasl_secprops != NULL ) {
581                         rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
582                                 (void *) sasl_secprops );
583                         
584                         if( rc != LDAP_OPT_SUCCESS ) {
585                                 fprintf( stderr,
586                                         "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
587                                         sasl_secprops );
588                                 return( EXIT_FAILURE );
589                         }
590                 }
591                 
592                 defaults = lutil_sasl_defaults( ld,
593                         sasl_mech,
594                         sasl_realm,
595                         sasl_authc_id,
596                         passwd.bv_val,
597                         sasl_authz_id );
598
599                 rc = ldap_sasl_interactive_bind_s( ld, binddn,
600                         sasl_mech, NULL, NULL,
601                         sasl_flags, lutil_sasl_interact, defaults );
602
603                 if( rc != LDAP_SUCCESS ) {
604                         ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
605                         return( EXIT_FAILURE );
606                 }
607 #else
608                 fprintf( stderr, "%s: not compiled with SASL support\n",
609                         argv[0] );
610                 return( EXIT_FAILURE );
611 #endif
612         }
613         else {
614                 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
615                                 != LDAP_SUCCESS ) {
616                         ldap_perror( ld, "ldap_bind" );
617                         return( EXIT_FAILURE );
618                 }
619         }
620
621         if( dn != NULL || oldpw != NULL || newpw != NULL ) {
622                 /* build change password control */
623                 BerElement *ber = ber_alloc_t( LBER_USE_DER );
624
625                 if( ber == NULL ) {
626                         perror( "ber_alloc_t" );
627                         ldap_unbind( ld );
628                         return EXIT_FAILURE;
629                 }
630
631                 ber_printf( ber, "{" /*}*/ );
632
633                 if( dn != NULL ) {
634                         ber_printf( ber, "ts",
635                                 LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, dn );
636                         free(dn);
637                 }
638
639                 if( oldpw != NULL ) {
640                         ber_printf( ber, "ts",
641                                 LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, oldpw );
642                         free(oldpw);
643                 }
644
645                 if( newpw != NULL ) {
646                         ber_printf( ber, "ts",
647                                 LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw );
648                         free(newpw);
649                 }
650
651                 ber_printf( ber, /*{*/ "N}" );
652
653                 rc = ber_flatten( ber, &bv );
654
655                 if( rc < 0 ) {
656                         perror( "ber_flatten" );
657                         ldap_unbind( ld );
658                         return EXIT_FAILURE;
659                 }
660
661                 ber_free( ber, 1 );
662         }
663
664         if ( not ) {
665                 rc = LDAP_SUCCESS;
666                 goto skip;
667         }
668
669         rc = ldap_extended_operation( ld,
670                 LDAP_EXOP_X_MODIFY_PASSWD, bv, 
671                 NULL, NULL, &id );
672
673         ber_bvfree( bv );
674
675         if( rc != LDAP_SUCCESS ) {
676                 ldap_perror( ld, "ldap_extended_operation" );
677                 ldap_unbind( ld );
678                 return EXIT_FAILURE;
679         }
680
681         rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res );
682         if ( rc < 0 ) {
683                 ldap_perror( ld, "ldappasswd: ldap_result" );
684                 return rc;
685         }
686
687         rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 0 );
688
689         if( rc != LDAP_SUCCESS ) {
690                 ldap_perror( ld, "ldap_parse_result" );
691                 return rc;
692         }
693
694         rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 1 );
695
696         if( rc != LDAP_SUCCESS ) {
697                 ldap_perror( ld, "ldap_parse_result" );
698                 return rc;
699         }
700
701         if( retdata != NULL ) {
702                 ber_tag_t tag;
703                 char *s;
704                 BerElement *ber = ber_init( retdata );
705
706                 if( ber == NULL ) {
707                         perror( "ber_init" );
708                         ldap_unbind( ld );
709                         return EXIT_FAILURE;
710                 }
711
712                 /* we should check the tag */
713                 tag = ber_scanf( ber, "{a}", &s);
714
715                 if( tag == LBER_ERROR ) {
716                         perror( "ber_scanf" );
717                 } else {
718                         printf("New password: %s\n", s);
719                         free( s );
720                 }
721
722                 ber_free( ber, 1 );
723         }
724
725         if( verbose || code != LDAP_SUCCESS || matcheddn || text || refs ) {
726                 printf( "Result: %s (%d)\n", ldap_err2string( code ), code );
727
728                 if( text && *text ) {
729                         printf( "Additional info: %s\n", text );
730                 }
731
732                 if( matcheddn && *matcheddn ) {
733                         printf( "Matched DN: %s\n", matcheddn );
734                 }
735
736                 if( refs ) {
737                         int i;
738                         for( i=0; refs[i]; i++ ) {
739                                 printf("Referral: %s\n", refs[i] );
740                         }
741                 }
742         }
743
744         ber_memfree( text );
745         ber_memfree( matcheddn );
746         ber_memvfree( (void **) refs );
747         ber_memfree( retoid );
748         ber_bvfree( retdata );
749
750 skip:
751         /* disconnect from server */
752         ldap_unbind (ld);
753
754         return EXIT_SUCCESS;
755 }