1/*	$NetBSD: passwd.c,v 1.1.1.3 2010/12/12 15:21:34 adam Exp $	*/
2
3/* OpenLDAP: pkg/ldap/libraries/libldap/passwd.c,v 1.18.2.5 2010/04/13 20:22:59 kurt Exp */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1998-2010 The OpenLDAP Foundation.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
11 * Public License.
12 *
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
16 */
17/* ACKNOWLEDGEMENTS:
18 * This program was orignally developed by Kurt D. Zeilenga for inclusion in
19 * OpenLDAP Software.
20 */
21
22#include "portable.h"
23
24#include <stdio.h>
25#include <ac/stdlib.h>
26#include <ac/string.h>
27#include <ac/time.h>
28
29#include "ldap-int.h"
30
31/*
32 * LDAP Password Modify (Extended) Operation (RFC 3062)
33 */
34
35int ldap_parse_passwd(
36	LDAP *ld,
37	LDAPMessage *res,
38	struct berval *newpasswd )
39{
40	int rc;
41	struct berval *retdata = NULL;
42
43	assert( ld != NULL );
44	assert( LDAP_VALID( ld ) );
45	assert( res != NULL );
46	assert( newpasswd != NULL );
47
48	newpasswd->bv_val = NULL;
49	newpasswd->bv_len = 0;
50
51	rc = ldap_parse_extended_result( ld, res, NULL, &retdata, 0 );
52	if ( rc != LDAP_SUCCESS ) {
53		return rc;
54	}
55
56	if ( retdata != NULL ) {
57		ber_tag_t tag;
58		BerElement *ber = ber_init( retdata );
59
60		if ( ber == NULL ) {
61			rc = ld->ld_errno = LDAP_NO_MEMORY;
62			goto done;
63		}
64
65		/* we should check the tag */
66		tag = ber_scanf( ber, "{o}", newpasswd );
67		ber_free( ber, 1 );
68
69		if ( tag == LBER_ERROR ) {
70			rc = ld->ld_errno = LDAP_DECODING_ERROR;
71		}
72	}
73
74done:;
75	ber_bvfree( retdata );
76
77	return rc;
78}
79
80int
81ldap_passwd( LDAP *ld,
82	struct berval	*user,
83	struct berval	*oldpw,
84	struct berval	*newpw,
85	LDAPControl		**sctrls,
86	LDAPControl		**cctrls,
87	int				*msgidp )
88{
89	int rc;
90	struct berval bv = BER_BVNULL;
91	BerElement *ber = NULL;
92
93	assert( ld != NULL );
94	assert( LDAP_VALID( ld ) );
95	assert( msgidp != NULL );
96
97	if( user != NULL || oldpw != NULL || newpw != NULL ) {
98		/* build change password control */
99		ber = ber_alloc_t( LBER_USE_DER );
100
101		if( ber == NULL ) {
102			ld->ld_errno = LDAP_NO_MEMORY;
103			return ld->ld_errno;
104		}
105
106		ber_printf( ber, "{" /*}*/ );
107
108		if( user != NULL ) {
109			ber_printf( ber, "tO",
110				LDAP_TAG_EXOP_MODIFY_PASSWD_ID, user );
111		}
112
113		if( oldpw != NULL ) {
114			ber_printf( ber, "tO",
115				LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, oldpw );
116		}
117
118		if( newpw != NULL ) {
119			ber_printf( ber, "tO",
120				LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, newpw );
121		}
122
123		ber_printf( ber, /*{*/ "N}" );
124
125		rc = ber_flatten2( ber, &bv, 0 );
126
127		if( rc < 0 ) {
128			ld->ld_errno = LDAP_ENCODING_ERROR;
129			return ld->ld_errno;
130		}
131
132	}
133
134	rc = ldap_extended_operation( ld, LDAP_EXOP_MODIFY_PASSWD,
135		bv.bv_val ? &bv : NULL, sctrls, cctrls, msgidp );
136
137	ber_free( ber, 1 );
138
139	return rc;
140}
141
142int
143ldap_passwd_s(
144	LDAP *ld,
145	struct berval	*user,
146	struct berval	*oldpw,
147	struct berval	*newpw,
148	struct berval *newpasswd,
149	LDAPControl **sctrls,
150	LDAPControl **cctrls )
151{
152	int		rc;
153	int		msgid;
154	LDAPMessage	*res;
155
156	rc = ldap_passwd( ld, user, oldpw, newpw, sctrls, cctrls, &msgid );
157	if ( rc != LDAP_SUCCESS ) {
158		return rc;
159	}
160
161	if ( ldap_result( ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res ) == -1 || !res ) {
162		return ld->ld_errno;
163	}
164
165	rc = ldap_parse_passwd( ld, res, newpasswd );
166	if( rc != LDAP_SUCCESS ) {
167		ldap_msgfree( res );
168		return rc;
169	}
170
171	return( ldap_result2error( ld, res, 1 ) );
172}
173