2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1998-2014 The OpenLDAP Foundation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
16 * This program was orignally developed by Kurt D. Zeilenga for inclusion in
23 #include <ac/stdlib.h>
24 #include <ac/string.h>
30 * LDAP Verify Credentials operation
32 * The request is an extended request with OID 1.3.6.1.4.1.4203.666.6.5 with value of
33 * the BER encoding of:
35 * VCRequest ::= SEQUENCE {
36 * cookie [0] OCTET STRING OPTIONAL,
38 * authentication AuthenticationChoice,
39 * controls [2] Controls OPTIONAL
42 * where LDAPDN, AuthenticationChoice, and Controls are as defined in RFC 4511.
44 * The response is an extended response with no OID and a value of the BER encoding of
46 * VCResponse ::= SEQUENCE {
47 * resultCode ResultCode,
48 * diagnosticMessage LDAPString,
49 * cookie [0] OCTET STRING OPTIONAL,
50 * serverSaslCreds [1] OCTET STRING OPTIONAL,
51 * controls [2] Controls OPTIONAL
54 * where ResultCode is the result code enumeration from RFC 4511, and LDAPString and Controls are as
55 * defined in RFC 4511.
58 int ldap_parse_verify_credentials(
63 struct berval **cookie,
64 struct berval **screds,
69 struct berval *retdata = NULL;
72 assert(LDAP_VALID(ld));
75 assert(diagmsg != NULL);
77 rc = ldap_parse_extended_result(ld, res, &retoid, &retdata, 0);
79 if( rc != LDAP_SUCCESS ) {
80 ldap_perror(ld, "ldap_parse_verify_credentials");
88 BerElement * ber = ber_init(retdata);
89 struct berval diagmsg_bv = BER_BVNULL;
91 rc = ld->ld_errno = LDAP_NO_MEMORY;
95 rc = LDAP_DECODING_ERROR;
97 if (ber_scanf(ber, "{im" /*"}"*/, &i, &diagmsg_bv) == LBER_ERROR) {
100 if ( diagmsg != NULL ) {
101 *diagmsg = LDAP_MALLOC( diagmsg_bv.bv_len + 1 );
102 AC_MEMCPY( *diagmsg, diagmsg_bv.bv_val, diagmsg_bv.bv_len );
103 (*diagmsg)[diagmsg_bv.bv_len] = '\0';
107 tag = ber_peek_tag(ber, &len);
108 if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE) {
109 if (ber_scanf(ber, "O", cookie) == LBER_ERROR)
111 tag = ber_peek_tag(ber, &len);
114 if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_SCREDS) {
115 if (ber_scanf(ber, "O", screds) == LBER_ERROR)
117 tag = ber_peek_tag(ber, &len);
120 if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS) {
124 *ctrls = LDAP_MALLOC(1 * sizeof(LDAPControl *));
131 *ctrls[nctrls] = NULL;
133 for(tag = ber_first_element(ber, &len, &opaque);
135 tag = ber_next_element(ber, &len, opaque))
138 LDAPControl **tctrls;
140 tctrl = LDAP_CALLOC(1, sizeof(LDAPControl));
142 /* allocate pointer space for current controls (nctrls)
143 * + this control + extra NULL
145 tctrls = !tctrl ? NULL : LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
148 /* allocation failure */
149 if (tctrl) LDAP_FREE(tctrl);
150 ldap_controls_free(*ctrls);
156 tctrls[nctrls++] = tctrl;
157 tctrls[nctrls] = NULL;
159 tag = ber_scanf(ber, "{a" /*"}"*/, &tctrl->ldctl_oid);
160 if (tag == LBER_ERROR) {
162 ldap_controls_free(tctrls);
166 tag = ber_peek_tag(ber, &len);
167 if (tag == LBER_BOOLEAN) {
169 tag = ber_scanf(ber, "b", &crit);
170 tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
171 tag = ber_peek_tag(ber, &len);
174 if (tag == LBER_OCTETSTRING) {
175 tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
177 BER_BVZERO( &tctrl->ldctl_value );
197 ldap_verify_credentials(LDAP *ld,
198 struct berval *cookie,
200 LDAP_CONST char *mechanism,
202 LDAPControl **vcctrls,
203 LDAPControl **sctrls,
204 LDAPControl **cctrls,
209 struct berval reqdata;
212 assert(LDAP_VALID(ld));
213 assert(msgidp != NULL);
215 ber = ber_alloc_t(LBER_USE_DER);
216 if (dn == NULL) dn = "";
218 if (mechanism == LDAP_SASL_SIMPLE) {
221 rc = ber_printf(ber, "{stO" /*"}"*/,
222 dn, LDAP_AUTH_SIMPLE, cred);
225 if (!cred || BER_BVISNULL(cred)) {
227 rc = ber_printf(ber, "{tOst{sN}" /*"}"*/,
228 LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, cookie,
229 dn, LDAP_AUTH_SASL, mechanism);
231 rc = ber_printf(ber, "{st{sN}N" /*"}"*/,
232 dn, LDAP_AUTH_SASL, mechanism);
236 rc = ber_printf(ber, "{tOst{sON}" /*"}"*/,
237 LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, cookie,
238 dn, LDAP_AUTH_SASL, mechanism, cred);
240 rc = ber_printf(ber, "{st{sON}" /*"}"*/,
241 dn, LDAP_AUTH_SASL, mechanism, cred);
247 rc = ld->ld_errno = LDAP_ENCODING_ERROR;
251 if (vcctrls && *vcctrls) {
252 LDAPControl *const *c;
254 rc = ber_printf(ber, "t{" /*"}"*/, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS);
256 for (c=vcctrls; *c; c++) {
257 rc = ldap_pvt_put_control(*c, ber);
258 if (rc != LDAP_SUCCESS) {
259 rc = ld->ld_errno = LDAP_ENCODING_ERROR;
264 rc = ber_printf(ber, /*"{{"*/ "}N}");
267 rc = ber_printf(ber, /*"{"*/ "N}");
271 rc = ld->ld_errno = LDAP_ENCODING_ERROR;
276 rc = ber_flatten2(ber, &reqdata, 0);
278 rc = ld->ld_errno = LDAP_ENCODING_ERROR;
282 rc = ldap_extended_operation(ld, LDAP_EXOP_VERIFY_CREDENTIALS,
283 &reqdata, sctrls, cctrls, msgidp);
291 ldap_verify_credentials_s(
293 struct berval *cookie,
295 LDAP_CONST char *mechanism,
297 LDAPControl **vcictrls,
298 LDAPControl **sctrls,
299 LDAPControl **cctrls,
302 struct berval **scookie,
303 struct berval **scred,
304 LDAPControl ***vcoctrls)
310 rc = ldap_verify_credentials(ld, cookie, dn, mechanism, cred, vcictrls, sctrls, cctrls, &msgid);
311 if (rc != LDAP_SUCCESS) return rc;
313 if (ldap_result(ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res) == -1 || !res) {
317 rc = ldap_parse_verify_credentials(ld, res, rcode, diagmsg, scookie, scred, vcoctrls);
318 if (rc != LDAP_SUCCESS) {
323 return( ldap_result2error(ld, res, 1));
326 #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS_INTERACTIVE
328 ldap_verify_credentials_interactive (
330 LDAP_CONST char *dn, /* usually NULL */
331 LDAP_CONST char *mech,
332 LDAPControl **vcControls,
333 LDAPControl **serverControls,
334 LDAPControl **clientControls,
336 /* should be client controls */
338 LDAP_SASL_INTERACT_PROC *proc,
342 /* as obtained from ldap_result() */
345 /* returned during bind processing */
349 if (!ld && context) {
353 assert(!serverControls);
359 /* special case to avoid having to expose a separate dispose context API */
360 sasl_dispose((sasl_conn_t)context);
364 ld->ld_errno = LDAP_NOT_SUPPORTED;