]> git.sur5r.net Git - openldap/blob - clients/tools/ldappasswd.c
85ef979468d08218b322fac05e3586d6d8e36472
[openldap] / clients / tools / ldappasswd.c
1 /* $OpenLDAP$ */
2 /*
3  * Copyright 1998-2003 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/socket.h>
15 #include <ac/string.h>
16 #include <ac/time.h>
17 #include <ac/unistd.h>
18
19 #include <ldap.h>
20 #include "lutil.h"
21 #include "lutil_ldap.h"
22 #include "ldap_defaults.h"
23
24 #include "common.h"
25
26
27 static struct berval newpw = { 0, NULL };
28 static struct berval oldpw = { 0, NULL };
29
30 static int   want_newpw = 0;
31 static int   want_oldpw = 0;
32
33 static char *oldpwfile = NULL;
34 static char *newpwfile = NULL;
35
36 void
37 usage( void )
38 {
39         fprintf(stderr,
40 "Change password of an LDAP user\n\n"
41 "usage: %s [options] [user]\n"
42 "  user: the autentication identity, commonly a DN\n"
43 "Password change options:\n"
44 "  -a secret  old password\n"
45 "  -A         prompt for old password\n"
46 "  -t file    read file for old password\n"
47 "  -s secret  new password\n"
48 "  -S         prompt for new password\n"
49 "  -T file    read file for new password\n"
50                 , prog );
51         tool_common_usage();
52         exit( EXIT_FAILURE );
53 }
54
55
56 const char options[] = "a:As:St:T:"
57         "Cd:D:e:h:H:InO:p:QR:U:vVw:WxX:y:Y:Z";
58
59 int
60 handle_private_option( int i )
61 {
62         switch ( i ) {
63 #if 0
64         case 'E': /* passwd controls */ {
65                 int             crit;
66                 char    *control, *cvalue;
67                 if( protocol == LDAP_VERSION2 ) {
68                         fprintf( stderr, "%s: -E incompatible with LDAPv%d\n",
69                                  prog, protocol );
70                         exit( EXIT_FAILURE );
71                 }
72
73                 /* should be extended to support comma separated list of
74                  *      [!]key[=value] parameters, e.g.  -E !foo,bar=567
75                  */
76
77                 crit = 0;
78                 cvalue = NULL;
79                 if( optarg[0] == '!' ) {
80                         crit = 1;
81                         optarg++;
82                 }
83
84                 control = strdup( optarg );
85                 if ( (cvalue = strchr( control, '=' )) != NULL ) {
86                         *cvalue++ = '\0';
87                 }
88
89                 fprintf( stderr, "Invalid passwd control name: %s\n", control );
90                 usage();
91                 }
92 #endif
93
94         case 'a':       /* old password (secret) */
95                 oldpw.bv_val = strdup( optarg );
96                 {
97                         char* p;
98                         for( p = optarg; *p != '\0'; p++ ) {
99                                 *p = '\0';
100                         }
101                 }
102                 oldpw.bv_len = strlen( oldpw.bv_val );
103                 break;
104
105         case 'A':       /* prompt for old password */
106                 want_oldpw++;
107                 break;
108
109         case 's':       /* new password (secret) */
110                 newpw.bv_val = strdup (optarg);
111                 {
112                         char* p;
113                         for( p = optarg; *p != '\0'; p++ ) {
114                                 *p = '\0';
115                         }
116                 }
117                 newpw.bv_len = strlen( newpw.bv_val );
118                 break;
119
120         case 'S':       /* prompt for user password */
121                 want_newpw++;
122                 break;
123
124         case 't':
125                 oldpwfile = optarg;
126                 break;
127
128         case 'T':
129                 newpwfile = optarg;
130                 break;
131
132         default:
133                 return 0;
134         }
135         return 1;
136 }
137
138
139 int
140 main( int argc, char *argv[] )
141 {
142         int rc;
143         char    *user = NULL;
144
145         LDAP           *ld = NULL;
146         struct berval bv = {0, NULL};
147         BerElement  *ber = NULL;
148
149         int id, code = LDAP_OTHER;
150         LDAPMessage *res;
151         char *matcheddn = NULL, *text = NULL, **refs = NULL;
152         char    *retoid = NULL;
153         struct berval *retdata = NULL;
154
155         prog = lutil_progname( "ldappasswd", argc, argv );
156
157         /* LDAPv3 only */
158         protocol = LDAP_VERSION3;
159
160         tool_args( argc, argv );
161
162         if( argc - optind > 1 ) {
163                 usage();
164         } else if ( argc - optind == 1 ) {
165                 user = strdup( argv[optind] );
166         } else {
167                 user = NULL;
168         }
169
170         if( oldpwfile ) {
171                 rc = lutil_get_filed_password( prog, &oldpw );
172                 if( rc ) return EXIT_FAILURE;
173         }
174
175         if( want_oldpw && oldpw.bv_val == NULL ) {
176                 /* prompt for old password */
177                 char *ckoldpw;
178                 oldpw.bv_val = strdup(getpassphrase("Old password: "));
179                 ckoldpw = getpassphrase("Re-enter old password: ");
180
181                 if( oldpw.bv_val == NULL || ckoldpw == NULL ||
182                         strcmp( oldpw.bv_val, ckoldpw ))
183                 {
184                         fprintf( stderr, "passwords do not match\n" );
185                         return EXIT_FAILURE;
186                 }
187
188                 oldpw.bv_len = strlen( oldpw.bv_val );
189         }
190
191         if( newpwfile ) {
192                 rc = lutil_get_filed_password( prog, &newpw );
193                 if( rc ) return EXIT_FAILURE;
194         }
195
196         if( want_newpw && newpw.bv_val == NULL ) {
197                 /* prompt for new password */
198                 char *cknewpw;
199                 newpw.bv_val = strdup(getpassphrase("New password: "));
200                 cknewpw = getpassphrase("Re-enter new password: ");
201
202                 if( newpw.bv_val == NULL || cknewpw == NULL ||
203                         strcmp( newpw.bv_val, cknewpw ))
204                 {
205                         fprintf( stderr, "passwords do not match\n" );
206                         return EXIT_FAILURE;
207                 }
208
209                 newpw.bv_len = strlen( newpw.bv_val );
210         }
211
212         if( want_bindpw && passwd.bv_val == NULL ) {
213                 /* handle bind password */
214                 passwd.bv_val = strdup( getpassphrase("Enter bind password: "));
215                 passwd.bv_len = passwd.bv_val ? strlen( passwd.bv_val ) : 0;
216         }
217
218         ld = tool_conn_setup( 0, 0 );
219
220         tool_bind( ld );
221
222         if ( authzid || manageDSAit || noop )
223                 tool_server_controls( ld, NULL, 0 );
224
225         if( user != NULL || oldpw.bv_val != NULL || newpw.bv_val != NULL ) {
226                 /* build change password control */
227                 ber = ber_alloc_t( LBER_USE_DER );
228
229                 if( ber == NULL ) {
230                         perror( "ber_alloc_t" );
231                         ldap_unbind( ld );
232                         return EXIT_FAILURE;
233                 }
234
235                 ber_printf( ber, "{" /*}*/ );
236
237                 if( user != NULL ) {
238                         ber_printf( ber, "ts",
239                                 LDAP_TAG_EXOP_MODIFY_PASSWD_ID, user );
240                         free(user);
241                 }
242
243                 if( oldpw.bv_val != NULL ) {
244                         ber_printf( ber, "tO",
245                                 LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, &oldpw );
246                         free(oldpw.bv_val);
247                 }
248
249                 if( newpw.bv_val != NULL ) {
250                         ber_printf( ber, "tO",
251                                 LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, &newpw );
252                         free(newpw.bv_val);
253                 }
254
255                 ber_printf( ber, /*{*/ "N}" );
256
257                 rc = ber_flatten2( ber, &bv, 0 );
258
259                 if( rc < 0 ) {
260                         perror( "ber_flatten2" );
261                         ldap_unbind( ld );
262                         return EXIT_FAILURE;
263                 }
264         }
265
266         if ( not ) {
267                 rc = LDAP_SUCCESS;
268                 goto skip;
269         }
270
271         rc = ldap_extended_operation( ld,
272                 LDAP_EXOP_MODIFY_PASSWD, bv.bv_val ? &bv : NULL, 
273                 NULL, NULL, &id );
274
275         ber_free( ber, 1 );
276
277         if( rc != LDAP_SUCCESS ) {
278                 ldap_perror( ld, "ldap_extended_operation" );
279                 ldap_unbind( ld );
280                 return EXIT_FAILURE;
281         }
282
283         rc = ldap_result( ld, LDAP_RES_ANY, LDAP_MSG_ALL, NULL, &res );
284         if ( rc < 0 ) {
285                 ldap_perror( ld, "ldappasswd: ldap_result" );
286                 return rc;
287         }
288
289         rc = ldap_parse_result( ld, res,
290                 &code, &matcheddn, &text, &refs, NULL, 0 );
291
292         if( rc != LDAP_SUCCESS ) {
293                 ldap_perror( ld, "ldap_parse_result" );
294                 return rc;
295         }
296
297         rc = ldap_parse_extended_result( ld, res, &retoid, &retdata, 1 );
298
299         if( rc != LDAP_SUCCESS ) {
300                 ldap_perror( ld, "ldap_parse_result" );
301                 return rc;
302         }
303
304         if( retdata != NULL ) {
305                 ber_tag_t tag;
306                 char *s;
307                 ber = ber_init( retdata );
308
309                 if( ber == NULL ) {
310                         perror( "ber_init" );
311                         ldap_unbind( ld );
312                         return EXIT_FAILURE;
313                 }
314
315                 /* we should check the tag */
316                 tag = ber_scanf( ber, "{a}", &s);
317
318                 if( tag == LBER_ERROR ) {
319                         perror( "ber_scanf" );
320                 } else {
321                         printf("New password: %s\n", s);
322                         free( s );
323                 }
324
325                 ber_free( ber, 1 );
326         }
327
328         if( verbose || code != LDAP_SUCCESS || matcheddn || text || refs ) {
329                 printf( "Result: %s (%d)\n", ldap_err2string( code ), code );
330
331                 if( text && *text ) {
332                         printf( "Additional info: %s\n", text );
333                 }
334
335                 if( matcheddn && *matcheddn ) {
336                         printf( "Matched DN: %s\n", matcheddn );
337                 }
338
339                 if( refs ) {
340                         int i;
341                         for( i=0; refs[i]; i++ ) {
342                                 printf("Referral: %s\n", refs[i] );
343                         }
344                 }
345         }
346
347         ber_memfree( text );
348         ber_memfree( matcheddn );
349         ber_memvfree( (void **) refs );
350         ber_memfree( retoid );
351         ber_bvfree( retdata );
352
353 skip:
354         /* disconnect from server */
355         ldap_unbind (ld);
356
357         return code == LDAP_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE;
358 }