]> git.sur5r.net Git - openldap/blob - clients/tools/ldappasswd.c
a5cd3db7ae960a5a8113c11224ab93a6ea34606e
[openldap] / clients / tools / ldappasswd.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-1999 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\trequest the use of TLS (-ZZ to make it critical)\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         char    *bindpw = 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                         bindpw = strdup (optarg);
162
163                         {
164                                 char* p;
165
166                                 for( p = optarg; *p == '\0'; p++ ) {
167                                         *p = '*';
168                                 }
169                         }
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(getpass("Old password: "));
250                 ckoldpw = getpass("Re-enter old password: ");
251
252                 if( strncmp( oldpw, ckoldpw, strlen(oldpw) )) {
253                         fprintf( stderr, "passwords do not match\n" );
254                         return EXIT_FAILURE;
255                 }
256         }
257
258         if( want_newpw && newpw == NULL ) {
259                 /* prompt for new password */
260                 char *cknewpw;
261                 newpw = strdup(getpass("New password: "));
262                 cknewpw = getpass("Re-enter new password: ");
263
264                 if( strncmp( newpw, cknewpw, strlen(newpw) )) {
265                         fprintf( stderr, "passwords do not match\n" );
266                         return EXIT_FAILURE;
267                 }
268         }
269
270         if( binddn == NULL && dn != NULL ) {
271                 binddn = dn;
272                 dn = NULL;
273
274                 if( bindpw == NULL ) bindpw = oldpw;
275         }
276
277         if (want_bindpw && bindpw == NULL ) {
278                 /* handle bind password */
279                 fprintf( stderr, "Bind DN: %s\n", binddn );
280                 bindpw = strdup( getpass("Enter bind password: "));
281         }
282
283         if ( debug ) {
284                 if( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug ) != LBER_OPT_SUCCESS ) {
285                         fprintf( stderr, "Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
286                 }
287                 if( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug ) != LDAP_OPT_SUCCESS ) {
288                         fprintf( stderr, "Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
289                 }
290         }
291
292 #ifdef SIGPIPE
293         (void) SIGNAL( SIGPIPE, SIG_IGN );
294 #endif
295
296         /* connect to server */
297         if ((ld = ldap_init( ldaphost, ldapport )) == NULL) {
298                 perror("ldap_init");
299                 return EXIT_FAILURE;
300         }
301
302         /* don't chase referrals */
303         ldap_set_option( ld, LDAP_OPT_REFERRALS, LDAP_OPT_OFF );
304
305         /* LDAPv3 only */
306         version = 3;
307         rc = ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
308
309         if(rc != LDAP_OPT_SUCCESS ) {
310                 fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", version );
311         }
312
313         if ( use_tls && ldap_start_tls( ld, NULL, NULL ) != LDAP_SUCCESS ) {
314                 if ( use_tls > 1 ) {
315                         ldap_perror( ld, "ldap_start_tls" );
316                         return( EXIT_FAILURE );
317                 }
318         }
319
320         if ( authmethod == LDAP_AUTH_SASL ) {
321 #ifdef HAVE_CYRUS_SASL
322                 int     minssf = 0, maxssf = 0;
323
324                 if ( sasl_integrity > 0 )
325                         maxssf = 1;
326                 if ( sasl_integrity > 1 )
327                         minssf = 1;
328                 if ( sasl_privacy > 0 )
329                         maxssf = 100000; /* Something big value */
330                 if ( sasl_privacy > 1 )
331                         minssf = 56;
332                 
333                 if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MINSSF,
334                                 (void *)&minssf ) != LDAP_OPT_SUCCESS ) {
335                         fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MINSSF"
336                                 "%d\n", minssf);
337                         return( EXIT_FAILURE );
338                 }
339                 if ( ldap_set_option( ld, LDAP_OPT_X_SASL_MAXSSF,
340                                 (void *)&maxssf ) != LDAP_OPT_SUCCESS ) {
341                         fprintf( stderr, "Could not set LDAP_OPT_X_SASL_MAXSSF"
342                                 "%d\n", maxssf);
343                         return( EXIT_FAILURE );
344                 }
345                 
346                 if ( ldap_negotiated_sasl_bind_s( ld, binddn, sasl_authc_id,
347                                 sasl_authz_id, sasl_mech, NULL, NULL, NULL )
348                                         != LDAP_SUCCESS ) {
349                         ldap_perror( ld, "ldap_sasl_bind" );
350                         return( EXIT_FAILURE );
351                 }
352 #else
353                 fprintf( stderr, "%s was not compiled with SASL support\n",
354                         argv[0] );
355                 return( EXIT_FAILURE );
356 #endif
357         }
358         else {
359                 if ( ldap_bind_s( ld, binddn, bindpw, authmethod )
360                                 != LDAP_SUCCESS ) {
361                         ldap_perror( ld, "ldap_bind" );
362                         return( EXIT_FAILURE );
363                 }
364         }
365
366         if( dn != NULL || oldpw != NULL || newpw != NULL ) {
367                 /* build change password control */
368                 BerElement *ber = ber_alloc_t( LBER_USE_DER );
369
370                 if( ber == NULL ) {
371                         perror( "ber_alloc_t" );
372                         ldap_unbind( ld );
373                         return EXIT_FAILURE;
374                 }
375
376                 ber_printf( ber, "{" /*}*/ );
377
378                 if( dn != NULL ) {
379                         ber_printf( ber, "ts",
380                                 LDAP_TAG_EXOP_X_MODIFY_PASSWD_ID, dn );
381                         free(dn);
382                 }
383
384                 if( oldpw != NULL ) {
385                         ber_printf( ber, "ts",
386                                 LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, oldpw );
387                         free(oldpw);
388                 }
389
390                 if( newpw != NULL ) {
391                         ber_printf( ber, "ts",
392                                 LDAP_TAG_EXOP_X_MODIFY_PASSWD_NEW, newpw );
393                         free(newpw);
394                 }
395
396                 ber_printf( ber, /*{*/ "}" );
397
398                 rc = ber_flatten( ber, &bv );
399
400                 if( rc < 0 ) {
401                         perror( "ber_flatten" );
402                         ldap_unbind( ld );
403                         return EXIT_FAILURE;
404                 }
405
406                 ber_free( ber, 1 );
407         }
408
409         rc = ldap_extended_operation_s( ld,
410                 LDAP_EXOP_X_MODIFY_PASSWD, bv, 
411                 NULL, NULL,
412                 &retoid, &retdata );
413
414         ber_bvfree( bv );
415
416         if( retdata != NULL ) {
417                 ber_tag_t tag;
418                 char *s;
419                 BerElement *ber = ber_init( retdata );
420
421                 if( ber == NULL ) {
422                         perror( "ber_init" );
423                         ldap_unbind( ld );
424                         return EXIT_FAILURE;
425                 }
426
427                 /* we should check the tag */
428                 tag = ber_scanf( ber, "{a}", &s);
429
430                 if( tag == LBER_ERROR ) {
431                         perror( "ber_scanf" );
432                 } else {
433                         printf("New password: %s\n", s);
434                         free( s );
435                 }
436
437                 ber_free( ber, 1 );
438         }
439
440         if ( rc != LDAP_SUCCESS ) {
441                 ldap_perror( ld, "ldap_extended_operation" );
442                 ldap_unbind( ld );
443                 return EXIT_FAILURE;
444         }
445
446         ldap_memfree( retoid );
447         ber_bvfree( retdata );
448
449         /* disconnect from server */
450         ldap_unbind (ld);
451
452         return EXIT_SUCCESS;
453 }