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