xref: /netbsd-src/external/bsd/openldap/dist/libraries/libldap/vc.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: vc.c,v 1.2 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: vc.c,v 1.2 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 Verify Credentials operation
36  *
37  * The request is an extended request with OID 1.3.6.1.4.1.4203.666.6.5 with value of
38  * the BER encoding of:
39  *
40  * VCRequest ::= SEQUENCE {
41  *		cookie [0] OCTET STRING OPTIONAL,
42  *		name	LDAPDN,
43  *		authentication	AuthenticationChoice,
44  *	    controls [2] Controls OPTIONAL
45  * }
46  *
47  * where LDAPDN, AuthenticationChoice, and Controls are as defined in RFC 4511.
48  *
49  * The response is an extended response with no OID and a value of the BER encoding of
50  *
51  * VCResponse ::= SEQUENCE {
52  *		resultCode ResultCode,
53  *		diagnosticMessage LDAPString,
54  *		cookie [0] OCTET STRING OPTIONAL,
55  *		serverSaslCreds [1] OCTET STRING OPTIONAL,
56  *	    controls [2] Controls OPTIONAL
57  * }
58  *
59  * where ResultCode is the result code enumeration from RFC 4511, and LDAPString and Controls are as
60  * defined in RFC 4511.
61  */
62 
ldap_parse_verify_credentials(LDAP * ld,LDAPMessage * res,int * code,char ** diagmsg,struct berval ** cookie,struct berval ** screds,LDAPControl *** ctrls)63 int ldap_parse_verify_credentials(
64 	LDAP *ld,
65 	LDAPMessage *res,
66 	int * code,
67 	char ** diagmsg,
68     struct berval **cookie,
69 	struct berval **screds,
70 	LDAPControl ***ctrls)
71 {
72 	int rc;
73 	char *retoid = NULL;
74 	struct berval *retdata = NULL;
75 
76 	assert(ld != NULL);
77 	assert(LDAP_VALID(ld));
78 	assert(res != NULL);
79 	assert(code != NULL);
80 	assert(diagmsg != NULL);
81 
82 	rc = ldap_parse_extended_result(ld, res, &retoid, &retdata, 0);
83 
84 	if( rc != LDAP_SUCCESS ) {
85 		ldap_perror(ld, "ldap_parse_verify_credentials");
86 		return rc;
87 	}
88 
89 	if (retdata) {
90 		ber_tag_t tag;
91 		ber_len_t len;
92 		ber_int_t i;
93 		BerElement * ber = ber_init(retdata);
94 		struct berval diagmsg_bv = BER_BVNULL;
95 		if (!ber) {
96 		    rc = ld->ld_errno = LDAP_NO_MEMORY;
97 			goto done;
98 		}
99 
100 		rc = LDAP_DECODING_ERROR;
101 
102 		if (ber_scanf(ber, "{im" /*"}"*/, &i, &diagmsg_bv) == LBER_ERROR) {
103 			goto ber_done;
104 		}
105 		if ( diagmsg != NULL ) {
106 			*diagmsg = LDAP_MALLOC( diagmsg_bv.bv_len + 1 );
107 			AC_MEMCPY( *diagmsg, diagmsg_bv.bv_val, diagmsg_bv.bv_len );
108 			(*diagmsg)[diagmsg_bv.bv_len] = '\0';
109 		}
110 		*code = i;
111 
112 		tag = ber_peek_tag(ber, &len);
113 		if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE) {
114 			if (ber_scanf(ber, "O", cookie) == LBER_ERROR)
115 				goto ber_done;
116 			tag = ber_peek_tag(ber, &len);
117 		}
118 
119 		if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_SCREDS) {
120 			if (ber_scanf(ber, "O", screds) == LBER_ERROR)
121 				goto ber_done;
122 			tag = ber_peek_tag(ber, &len);
123 		}
124 
125 		if (tag == LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS) {
126 		    int nctrls = 0;
127 			char * opaque;
128 
129 		    *ctrls = LDAP_MALLOC(1 * sizeof(LDAPControl *));
130 
131 			if (!*ctrls) {
132 				rc = LDAP_NO_MEMORY;
133 				goto ber_done;
134 			}
135 
136 			*ctrls[nctrls] = NULL;
137 
138 			for(tag = ber_first_element(ber, &len, &opaque);
139 				tag != LBER_ERROR;
140 				tag = ber_next_element(ber, &len, opaque))
141 		    {
142 				LDAPControl *tctrl;
143 				LDAPControl **tctrls;
144 
145 				tctrl = LDAP_CALLOC(1, sizeof(LDAPControl));
146 
147 				/* allocate pointer space for current controls (nctrls)
148 				 * + this control + extra NULL
149 				 */
150 				tctrls = !tctrl ? NULL : LDAP_REALLOC(*ctrls, (nctrls+2) * sizeof(LDAPControl *));
151 
152 				if (!tctrls) {
153 					/* allocation failure */
154 					if (tctrl) LDAP_FREE(tctrl);
155 					ldap_controls_free(*ctrls);
156 					*ctrls = NULL;
157 				    rc = LDAP_NO_MEMORY;
158 				    goto ber_done;
159 				}
160 
161 				tctrls[nctrls++] = tctrl;
162 				tctrls[nctrls] = NULL;
163 
164 				tag = ber_scanf(ber, "{a" /*"}"*/, &tctrl->ldctl_oid);
165 				if (tag == LBER_ERROR) {
166 					*ctrls = NULL;
167 					ldap_controls_free(tctrls);
168 					goto ber_done;
169 				}
170 
171 				tag = ber_peek_tag(ber, &len);
172 				if (tag == LBER_BOOLEAN) {
173 					ber_int_t crit;
174 					tag = ber_scanf(ber, "b", &crit);
175 					tctrl->ldctl_iscritical = crit ? (char) 0 : (char) ~0;
176 				    tag = ber_peek_tag(ber, &len);
177 				}
178 
179 			    if (tag == LBER_OCTETSTRING) {
180                     tag = ber_scanf( ber, "o", &tctrl->ldctl_value );
181                 } else {
182                     BER_BVZERO( &tctrl->ldctl_value );
183                 }
184 
185                 *ctrls = tctrls;
186 			}
187 	    }
188 
189 		rc = LDAP_SUCCESS;
190 
191 	ber_done:
192 	    ber_free(ber, 1);
193     }
194 
195 done:
196 	ber_bvfree(retdata);
197 	ber_memfree(retoid);
198 	return rc;
199 }
200 
201 int
ldap_verify_credentials(LDAP * ld,struct berval * cookie,LDAP_CONST char * dn,LDAP_CONST char * mechanism,struct berval * cred,LDAPControl ** vcctrls,LDAPControl ** sctrls,LDAPControl ** cctrls,int * msgidp)202 ldap_verify_credentials(LDAP *ld,
203 	struct berval	*cookie,
204 	LDAP_CONST char *dn,
205 	LDAP_CONST char *mechanism,
206 	struct berval	*cred,
207     LDAPControl		**vcctrls,
208 	LDAPControl		**sctrls,
209 	LDAPControl		**cctrls,
210 	int				*msgidp)
211 {
212 	int rc;
213 	BerElement *ber;
214 	struct berval reqdata;
215 
216 	assert(ld != NULL);
217 	assert(LDAP_VALID(ld));
218 	assert(msgidp != NULL);
219 
220 	ber = ber_alloc_t(LBER_USE_DER);
221 	if (dn == NULL) dn = "";
222 
223 	if (mechanism == LDAP_SASL_SIMPLE) {
224 		assert(!cookie);
225 
226 		rc = ber_printf(ber, "{stO" /*"}"*/,
227 			dn, LDAP_AUTH_SIMPLE, cred);
228 
229 	} else {
230 		if (!cred || BER_BVISNULL(cred)) {
231 			if (cookie) {
232 				rc = ber_printf(ber, "{tOst{sN}" /*"}"*/,
233 					LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, cookie,
234 					dn, LDAP_AUTH_SASL, mechanism);
235 			} else {
236 				rc = ber_printf(ber, "{st{sN}N" /*"}"*/,
237 					dn, LDAP_AUTH_SASL, mechanism);
238 			}
239 		} else {
240 			if (cookie) {
241 				rc = ber_printf(ber, "{tOst{sON}" /*"}"*/,
242 					LDAP_TAG_EXOP_VERIFY_CREDENTIALS_COOKIE, cookie,
243 					dn, LDAP_AUTH_SASL, mechanism, cred);
244 			} else {
245 				rc = ber_printf(ber, "{st{sON}" /*"}"*/,
246 					dn, LDAP_AUTH_SASL, mechanism, cred);
247 			}
248 		}
249 	}
250 
251 	if (rc < 0) {
252 		rc = ld->ld_errno = LDAP_ENCODING_ERROR;
253 		goto done;
254 	}
255 
256 	if (vcctrls && *vcctrls) {
257 		LDAPControl *const *c;
258 
259 		rc = ber_printf(ber, "t{" /*"}"*/, LDAP_TAG_EXOP_VERIFY_CREDENTIALS_CONTROLS);
260 
261 		for (c=vcctrls; *c; c++) {
262 			rc = ldap_pvt_put_control(*c, ber);
263 			if (rc != LDAP_SUCCESS) {
264 				rc = ld->ld_errno = LDAP_ENCODING_ERROR;
265 				goto done;
266 			}
267 		}
268 
269 		rc = ber_printf(ber, /*"{{"*/ "}N}");
270 
271 	} else {
272 		rc = ber_printf(ber, /*"{"*/ "N}");
273 	}
274 
275 	if (rc < 0) {
276 		rc = ld->ld_errno = LDAP_ENCODING_ERROR;
277 		goto done;
278 	}
279 
280 
281 	rc = ber_flatten2(ber, &reqdata, 0);
282 	if (rc < 0) {
283 		rc = ld->ld_errno = LDAP_ENCODING_ERROR;
284 		goto done;
285 	}
286 
287 	rc = ldap_extended_operation(ld, LDAP_EXOP_VERIFY_CREDENTIALS,
288 		&reqdata, sctrls, cctrls, msgidp);
289 
290 done:
291 	ber_free(ber, 1);
292 	return rc;
293 }
294 
295 int
ldap_verify_credentials_s(LDAP * ld,struct berval * cookie,LDAP_CONST char * dn,LDAP_CONST char * mechanism,struct berval * cred,LDAPControl ** vcictrls,LDAPControl ** sctrls,LDAPControl ** cctrls,int * rcode,char ** diagmsg,struct berval ** scookie,struct berval ** scred,LDAPControl *** vcoctrls)296 ldap_verify_credentials_s(
297 	LDAP *ld,
298 	struct berval	*cookie,
299 	LDAP_CONST char *dn,
300 	LDAP_CONST char *mechanism,
301 	struct berval	*cred,
302     LDAPControl		**vcictrls,
303 	LDAPControl		**sctrls,
304 	LDAPControl		**cctrls,
305 	int				*rcode,
306 	char 			**diagmsg,
307 	struct berval	**scookie,
308 	struct berval	**scred,
309     LDAPControl		***vcoctrls)
310 {
311 	int				rc;
312 	int				msgid;
313 	LDAPMessage		*res;
314 
315 	rc = ldap_verify_credentials(ld, cookie, dn, mechanism, cred, vcictrls, sctrls, cctrls, &msgid);
316 	if (rc != LDAP_SUCCESS) return rc;
317 
318 	if (ldap_result(ld, msgid, LDAP_MSG_ALL, (struct timeval *) NULL, &res) == -1 || !res) {
319 		return ld->ld_errno;
320 	}
321 
322 	rc = ldap_parse_verify_credentials(ld, res, rcode, diagmsg, scookie, scred, vcoctrls);
323 	if (rc != LDAP_SUCCESS) {
324 		ldap_msgfree(res);
325 		return rc;
326 	}
327 
328 	return( ldap_result2error(ld, res, 1));
329 }
330 
331 #ifdef LDAP_API_FEATURE_VERIFY_CREDENTIALS_INTERACTIVE
332 int
ldap_verify_credentials_interactive(LDAP * ld,LDAP_CONST char * dn,LDAP_CONST char * mech,LDAPControl ** vcControls,LDAPControl ** serverControls,LDAPControl ** clientControls,unsigned flags,LDAP_SASL_INTERACT_PROC * proc,void * defaults,void * context;LDAPMessage * result,const char ** rmech,int * msgid)333 ldap_verify_credentials_interactive (
334 	LDAP *ld,
335 	LDAP_CONST char *dn, /* usually NULL */
336 	LDAP_CONST char *mech,
337 	LDAPControl **vcControls,
338 	LDAPControl **serverControls,
339 	LDAPControl **clientControls,
340 
341 	/* should be client controls */
342 	unsigned flags,
343 	LDAP_SASL_INTERACT_PROC *proc,
344 	void *defaults,
345     void *context;
346 
347 	/* as obtained from ldap_result() */
348 	LDAPMessage *result,
349 
350 	/* returned during bind processing */
351 	const char **rmech,
352 	int *msgid )
353 {
354 	if (!ld && context) {
355 		assert(!dn);
356 		assert(!mech);
357 		assert(!vcControls);
358 		assert(!serverControls);
359 		assert(!defaults);
360 		assert(!result);
361 		assert(!rmech);
362 		assert(!msgid);
363 
364 		/* special case to avoid having to expose a separate dispose context API */
365 		sasl_dispose((sasl_conn_t)context);
366         return LDAP_SUCCESS;
367     }
368 
369     ld->ld_errno = LDAP_NOT_SUPPORTED;
370     return ld->ld_errno;
371 }
372 #endif
373