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