]> git.sur5r.net Git - openldap/blob - clients/tools/ldappasswd.c
91dd6fb53babbfdeec7c6db47120598436209680
[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 the password of an LDAP entry\n\n"
32 "usage: %s [options] dn\n"
33 "       dn: the DN of the entry whose password must be changed\n"
34 "Password change options:\n"
35 "       -a secret\told password\n"
36 "       -A\t\tprompt for old password\n"
37 "       -s secret\tnew password\n"
38 "       -S\t\tprompt for new password\n"
39
40 "Common options:\n"
41 "       -d level\tdebugging level\n"
42 "       -C\t\tchase referrals\n"
43 "       -D binddn\tbind DN\n"
44 "       -h host\t\tLDAP server (default: localhost)\n"
45 "       -n\t\tmake no modifications\n"
46 "       -O secprops\tSASL security properties\n"
47 "       -p port\t\tport on LDAP server\n"
48 "       -U user\t\tSASL authentication identity (username)\n"
49 "       -v\t\tverbose mode\n"
50 "       -w passwd\tbind password (for simple authentication)\n"
51 "       -W\t\tprompt for bind password\n"
52 "       -x\t\tSimple authentication\n"
53 "       -X id\t\tSASL authorization identity (\"dn:<dn>\" or \"u:<user>\")\n"
54 "       -Y mech\t\tSASL mechanism\n"
55 "       -Z\t\tissue Start TLS request (-ZZ to require successful response)\n"
56                 , s );
57
58         exit( EXIT_FAILURE );
59 }
60
61 int
62 main( int argc, char *argv[] )
63 {
64         int rc;
65         char    *prog = NULL;
66         char    *ldaphost = NULL;
67
68         char    *dn = NULL;
69         char    *binddn = NULL;
70
71         struct berval passwd = { 0, NULL };
72         char    *newpw = NULL;
73         char    *oldpw = NULL;
74
75         int             want_bindpw = 0;
76         int             want_newpw = 0;
77         int             want_oldpw = 0;
78
79         int             noupdates = 0;
80         int             i;
81         int             ldapport = 0;
82         int             debug = 0;
83         int             version = -1;
84         int             authmethod = -1;
85 #ifdef HAVE_CYRUS_SASL
86         char            *sasl_authc_id = NULL;
87         char            *sasl_authz_id = NULL;
88         char            *sasl_mech = NULL;
89         char            *sasl_secprops = NULL;
90 #endif
91         int             use_tls = 0;
92         int             referrals = 0;
93         LDAP           *ld;
94         struct berval *bv = NULL;
95
96         int id, code;
97         LDAPMessage *res;
98         char *matcheddn = NULL, *text = NULL, **refs = NULL;
99         char    *retoid = NULL;
100         struct berval *retdata = NULL;
101
102     prog = (prog = strrchr(argv[0], *LDAP_DIRSEP)) == NULL ? argv[0] : ++prog;
103
104         if (argc == 1)
105                 usage (argv[0]);
106
107         while( (i = getopt( argc, argv,
108                 "Aa:Ss:" "Cd:D:h:nO:p:U:vw:WxX:Y:Z" )) != EOF )
109         {
110                 switch (i) {
111                 /* Password Options */
112                 case 'A':       /* prompt for old password */
113                         want_oldpw++;
114                         break;
115
116                 case 'a':       /* old password (secret) */
117                         oldpw = strdup (optarg);
118
119                         {
120                                 char* p;
121
122                                 for( p = optarg; *p == '\0'; p++ ) {
123                                         *p = '*';
124                                 }
125                         }
126                         break;
127
128                 case 'S':       /* prompt for user password */
129                         want_newpw++;
130                         break;
131
132                 case 's':       /* new password (secret) */
133                         newpw = strdup (optarg);
134                         {
135                                 char* p;
136
137                                 for( p = optarg; *p == '\0'; p++ ) {
138                                         *p = '*';
139                                 }
140                         }
141                         break;
142
143                 /* Common Options */
144                 case 'C':
145                         referrals++;
146                         break;
147
148                 case 'D':       /* bind distinguished name */
149                         binddn = strdup (optarg);
150                         break;
151
152                 case 'd':       /* debugging option */
153                         debug |= atoi (optarg);
154                         break;
155
156                 case 'h':       /* ldap host */
157                         ldaphost = strdup (optarg);
158                         break;
159
160                 case 'n':       /* don't update entry(s) */
161                         noupdates++;
162                         break;
163
164                 case 'p':       /* ldap port */
165                         ldapport = strtol( optarg, NULL, 10 );
166                         break;
167
168                 case 'v':       /* verbose */
169                         verbose++;
170                         break;
171
172                 case 'W':       /* prompt for bind password */
173                         want_bindpw++;
174                         break;
175
176                 case 'w':       /* bind password */
177                         passwd.bv_val = strdup (optarg);
178                         {
179                                 char* p;
180
181                                 for( p = optarg; *p == '\0'; p++ ) {
182                                         *p = '*';
183                                 }
184                         }
185                         passwd.bv_len = strlen( passwd.bv_val );
186                         break;
187
188                 case 'O':
189 #ifdef HAVE_CYRUS_SASL
190                         sasl_secprops = strdup( optarg );
191                         authmethod = LDAP_AUTH_SASL;
192 #else
193                         fprintf( stderr, "%s was not compiled with SASL support\n",
194                                 argv[0] );
195                         return( EXIT_FAILURE );
196 #endif
197                         break;
198                 case 'Y':
199 #ifdef HAVE_CYRUS_SASL
200                         if ( strcasecmp( optarg, "any" ) &&
201                                         strcmp( optarg, "*" ) ) {
202                                 sasl_mech = strdup( optarg );
203                         }
204                         authmethod = LDAP_AUTH_SASL;
205 #else
206                         fprintf( stderr, "%s was not compiled with SASL "
207                                 "support\n", argv[0] );
208                         return( EXIT_FAILURE );
209 #endif
210                         break;
211                 case 'U':
212 #ifdef HAVE_CYRUS_SASL
213                         sasl_authc_id = strdup( optarg );
214                         authmethod = LDAP_AUTH_SASL;
215 #else
216                         fprintf( stderr, "%s was not compiled with SASL "
217                                 "support\n", argv[0] );
218                         return( EXIT_FAILURE );
219 #endif
220                         break;
221                 case 'x':
222                         if( authmethod != -1 && authmethod != LDAP_AUTH_SIMPLE ) {
223                                 fprintf( stderr, "%s: incompatible with previous "
224                                         "authentication choice\n", prog );
225                                 return EXIT_FAILURE;
226                         }
227                         authmethod = LDAP_AUTH_SIMPLE;
228                         break;
229                 case 'X':
230 #ifdef HAVE_CYRUS_SASL
231                         sasl_authz_id = strdup( optarg );
232                         authmethod = LDAP_AUTH_SASL;
233 #else
234                         fprintf( stderr, "%s was not compiled with SASL "
235                                 "support\n", argv[0] );
236                         return( EXIT_FAILURE );
237 #endif
238                         break;
239                 case 'Z':
240 #ifdef HAVE_TLS
241                         use_tls++;
242 #else
243                         fprintf( stderr, "%s was not compiled with TLS "
244                                 "support\n", argv[0] );
245                         return( EXIT_FAILURE );
246 #endif
247                         break;
248
249                 default:
250                         fprintf( stderr, "%s: unrecongized option -%c\n",
251                                 prog, optopt );
252                         usage (argv[0]);
253                 }
254         }
255
256         if( argc - optind != 1 ) {
257                 usage( argv[0] );
258         } 
259
260         dn = strdup( argv[optind] );
261
262         if( want_oldpw && oldpw == NULL ) {
263                 /* prompt for old password */
264                 char *ckoldpw;
265                 newpw = strdup(getpassphrase("Old password: "));
266                 ckoldpw = getpassphrase("Re-enter old password: ");
267
268                 if( newpw== NULL || ckoldpw == NULL ||
269                         strncmp( oldpw, ckoldpw, strlen(oldpw) ))
270                 {
271                         fprintf( stderr, "passwords do not match\n" );
272                         return EXIT_FAILURE;
273                 }
274         }
275
276         if( want_newpw && newpw == NULL ) {
277                 /* prompt for new password */
278                 char *cknewpw;
279                 newpw = strdup(getpassphrase("New password: "));
280                 cknewpw = getpassphrase("Re-enter new password: ");
281
282                 if( newpw== NULL || cknewpw == NULL ||
283                         strncmp( newpw, cknewpw, strlen(newpw) ))
284                 {
285                         fprintf( stderr, "passwords do not match\n" );
286                         return EXIT_FAILURE;
287                 }
288         }
289
290         if( binddn == NULL && dn != NULL ) {
291                 binddn = dn;
292                 dn = NULL;
293
294                 if( passwd.bv_val == NULL ) {
295                         passwd.bv_val = oldpw;
296                         passwd.bv_len = oldpw == NULL ? 0 : strlen( oldpw );
297                 }
298         }
299
300         if (want_bindpw && passwd.bv_val == NULL ) {
301                 /* handle bind password */
302                 fprintf( stderr, "Bind DN: %s\n", binddn );
303                 passwd.bv_val = strdup( getpassphrase("Enter bind password: "));
304                 passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
305         }
306
307         if ( debug ) {
308                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
309                         fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
310                 }
311                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
312                         fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
313                 }
314         }
315
316 #ifdef SIGPIPE
317         (void) SIGNAL( SIGPIPE, SIG_IGN );
318 #endif
319
320         /* connect to server */
321         if ((ld = ldap_init( ldaphost, ldapport )) == NULL) {
322                 perror("ldap_init");
323                 return EXIT_FAILURE;
324         }
325
326         /* referrals */
327         if (ldap_set_option( ld, LDAP_OPT_REFERRALS,
328                 referrals ? LDAP_OPT_ON : LDAP_OPT_OFF ) != LDAP_OPT_SUCCESS )
329         {
330                 fprintf( stderr, "Could not set LDAP_OPT_REFERRALS %s\n",
331                         referrals ? "on" : "off" );
332                 return EXIT_FAILURE;
333         }
334
335         /* LDAPv3 only */
336         version = 3;
337         rc = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
338
339         if(rc != LDAP_OPT_SUCCESS ) {
340                 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
341                 return EXIT_FAILURE;
342         }
343
344         if ( use_tls && ldap_start_tls_s( ld, NULL, NULL ) != LDAP_SUCCESS ) {
345                 if ( use_tls > 1 ) {
346                         ldap_perror( ld, "ldap_start_tls" );
347                         return( EXIT_FAILURE );
348                 }
349                 fprintf( stderr, "WARNING: could not start TLS\n" );
350         }
351
352         if ( authmethod == LDAP_AUTH_SASL ) {
353 #ifdef HAVE_CYRUS_SASL
354                 if( sasl_secprops != NULL ) {
355                         rc = ldap_set_option( ld, LDAP_OPT_X_SASL_SECPROPS,
356                                 (void *) sasl_secprops );
357                         
358                         if( rc != LDAP_OPT_SUCCESS ) {
359                                 fprintf( stderr,
360                                         "Could not set LDAP_OPT_X_SASL_SECPROPS: %s\n",
361                                         sasl_secprops );
362                                 return( EXIT_FAILURE );
363                         }
364                 }
365                 
366                 rc = ldap_sasl_interactive_bind_s( ld, binddn,
367                         sasl_mech, NULL, NULL, lutil_sasl_interact );
368
369                 if( rc != LDAP_SUCCESS ) {
370                         ldap_perror( ld, "ldap_sasl_interactive_bind_s" );
371                         return( EXIT_FAILURE );
372                 }
373 #else
374                 fprintf( stderr, "%s was not compiled with SASL support\n",
375                         argv[0] );
376                 return( EXIT_FAILURE );
377 #endif
378         }
379         else {
380                 if ( ldap_bind_s( ld, binddn, passwd.bv_val, authmethod )
381                                 != LDAP_SUCCESS ) {
382                         ldap_perror( ld, "ldap_bind" );
383                         return( EXIT_FAILURE );
384                 }
385         }
386
387         if( dn != NULL || oldpw != NULL || newpw != NULL ) {
388                 /* build change password control */
389                 BerElement *ber = ber_alloc_t( LBER_USE_DER );
390
391                 if( ber == NULL ) {
392                         perror( "ber_alloc_t" );
393                         ldap_unbind( ld );
394                         return EXIT_FAILURE;
395                 }
396
397                 ber_printf( ber, "{" /*}*/ );
398
399                 if( dn != NULL ) {
400                         ber_printf( ber, "ts",
401                                 LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, dn );
402                         free(dn);
403                 }
404
405                 if( oldpw != NULL ) {
406                         ber_printf( ber, "ts",
407                                 LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, oldpw );
408                         free(oldpw);
409                 }
410
411                 if( newpw != NULL ) {
412                         ber_printf( ber, "ts",
413                                 LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw );
414                         free(newpw);
415                 }
416
417                 ber_printf( ber, /*{*/ "N}" );
418
419                 rc = ber_flatten( ber, &bv );
420
421                 if( rc < 0 ) {
422                         perror( "ber_flatten" );
423                         ldap_unbind( ld );
424                         return EXIT_FAILURE;
425                 }
426
427                 ber_free( ber, 1 );
428         }
429
430         if ( noupdates ) {
431                 rc = LDAP_SUCCESS;
432                 goto skip;
433         }
434
435         rc = ldap_extended_operation( ld,
436                 LDAP_EXOP_X_MODIFY_PASSWD, bv, 
437                 NULL, NULL, &id );
438
439         ber_bvfree( bv );
440
441         if( rc != LDAP_SUCCESS ) {
442                 ldap_perror( ld, "ldap_extended_operation" );
443                 ldap_unbind( ld );
444                 return EXIT_FAILURE;
445         }
446
447         rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res );
448         if ( rc < 0 ) {
449                 ldap_perror( ld, "ldappasswd: ldap_result" );
450                 return rc;
451         }
452
453         rc = ldap_parse_result( ld, res, &code, &matcheddn, &text, &refs, NULL, 0 );
454
455         if( rc != LDAP_SUCCESS ) {
456                 ldap_perror( ld, "ldap_parse_result" );
457                 return rc;
458         }
459
460         rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 1 );
461
462         if( rc != LDAP_SUCCESS ) {
463                 ldap_perror( ld, "ldap_parse_result" );
464                 return rc;
465         }
466
467         if( retdata != NULL ) {
468                 ber_tag_t tag;
469                 char *s;
470                 BerElement *ber = ber_init( retdata );
471
472                 if( ber == NULL ) {
473                         perror( "ber_init" );
474                         ldap_unbind( ld );
475                         return EXIT_FAILURE;
476                 }
477
478                 /* we should check the tag */
479                 tag = ber_scanf( ber, "{a}", &s);
480
481                 if( tag == LBER_ERROR ) {
482                         perror( "ber_scanf" );
483                 } else {
484                         printf("New password: %s\n", s);
485                         free( s );
486                 }
487
488                 ber_free( ber, 1 );
489         }
490
491         if( verbose || code != LDAP_SUCCESS || matcheddn || text || refs ) {
492                 printf( "Result: %s (%d)\n", ldap_err2string( code ), code );
493
494                 if( text && *text ) {
495                         printf( "Additional info: %s\n", text );
496                 }
497
498                 if( matcheddn && *matcheddn ) {
499                         printf( "Matched DN: %s\n", matcheddn );
500                 }
501
502                 if( refs ) {
503                         int i;
504                         for( i=0; refs[i]; i++ ) {
505                                 printf("Referral: %s\n", refs[i] );
506                         }
507                 }
508         }
509
510         ber_memfree( text );
511         ber_memfree( matcheddn );
512         ber_memvfree( (void **) refs );
513         ber_memfree( retoid );
514         ber_bvfree( retdata );
515
516 skip:
517         /* disconnect from server */
518         ldap_unbind (ld);
519
520         return EXIT_SUCCESS;
521 }